Python语言系列-04-高阶函数
阅读原文时间:2023年07月10日阅读:4



#!/usr/bin/env python3
# author:Alnk(李成果)

# 什么是闭包
# 1,闭包存在于函数中
# 2,闭包就是内层函数对外层函数(非全局变量)的引用
# 3,最内层函数名会被逐层的返回,直至返回给最外层

# 不是闭包,name 是全局变量
# name = 1
# def func():
#     print(name)

# 这才是闭包
def func():
    name = 'tom'
    def inner():
        print(name)
    return inner

ret = func()
print(ret.__closure__)  # (<cell ...>,) 如果返回cell,就证明是一个闭包。返回None 就不是闭包
print(ret.__closure__[0].cell_contents)
print("------------- 1 --------------------")

# 这也是闭包
def func(name):
    # name = 'tom'    # name参数 相当于这行代码
    def inner():
        print(name)
    return inner

n1 = 'tom'
ret = func(n1)
print(ret.__closure__)
print("------------- 2 --------------------")

# 闭包的作用
# 解释器遇到闭包,会触发一个机制,这个闭包不会随着函数的结束而释放
# 1,不是闭包的情况,函数里面定义的变量会随着函数的结束而释放
def func(step):
    num = 1
    num += step
    print(num)
for i in range(5):
    func(2)
print("------------- 3 --------------------")
# 3 3 3 3 3

# 2,闭包情况下:不会随着函数的结束而释放
def func(step):
    num = 1
    def inner():
        nonlocal num
        num += step
        print(num)
    return inner
f = func(2)
for i in range(5):
    f()
print("------------- 4 --------------------")
# 3 5 7 9 11

# 闭包举例 爬虫
from urllib.request import urlopen
import ssl

def but():
    ssl._create_default_https_context = ssl._create_unverified_context  # 取消ssl证书验证
    context = urlopen("https://www.cnblogs.com/lichengguo/p/14649122.html").read()
    def get_content():
        return context
    return get_content

fn = but()
content = fn()  # 获取内容
print(content.decode('utf-8'))  # 中文显示

## 中间又执行了很多步程序,然后再次调用爬虫爬取的内容
## 不需要再次请求URL了,直接从变量中获取内容即可
content2 = fn()
print(content2.decode('utf-8'))



#!/usr/bin/env python3
# author:Alnk(李成果)
import time

# 装饰器
# 需求 测试其他函数的执行效率

# 第一版:写一个功能函数测试其他同事的函数执行效率
def func():
    time.sleep(0.2)
    print('非常复杂的函数')

def func1():
    time.sleep(0.3)
    print('超级复杂的函数')

# 如果被测试的函数很多的话,代码不能重用,会冗余
start_time = time.time()
func()
end_time = time.time()
print('此函数耗时秒数 %s' % (end_time - start_time))
print("------------------ 1 -----------------------")

# 第二版:函数实现这个功能
def func():
    time.sleep(0.2)
    print('非常复杂')

def func1():
    time.sleep(0.3)
    print('超级复杂')

def timmer(f):
    start_time = time.time()
    f()
    end_time = time.time()
    print('此函数耗时秒数 %s' % (end_time - start_time))

timmer(func)
timmer(func1)
print("------------------ 2 -----------------------")
# 假如函数有1500个,那么你1500个timmer(func),工作量很大
# 你要在不改变函数执行的指令下,同时测试效率

# 第三版:在不改变函数的执行方式下,同时测试执行效率
def func():
    time.sleep(0.2)
    print('非常复杂')

def func1():
    time.sleep(0.3)
    print('超级复杂')

def timmer(f):
    start_time = time.time()
    f()
    end_time = time.time()
    print('此函数耗时秒数 %s' % (end_time - start_time))

f1 = func
func = timmer
func(f1)  # timmer(func)
print("------------------ 3 -----------------------")

# 第四版:装饰器雏形
def func():
    time.sleep(0.2)
    print('非常复杂')

def func1():
    time.sleep(0.3)
    print('超级复杂')

def timmer(f):  # f = func 函数名
    def inner():
        start_time = time.time()
        f()
        end_time = time.time()
        print('此函数耗时秒数 %s' % (end_time - start_time))
    return  inner

func = timmer(func)  # 执行timmer函数,将func函数名传给f。等到返回值inner函数名,所以func --> inner
func()
print("------------------ 4 -----------------------")

# 第五版:装饰器雏形的优化,语法糖@
def timmer(f):  # f = func 函数名
    def inner():
        start_time = time.time()
        f()
        end_time = time.time()
        print('此函数耗时秒数 %s' % (end_time - start_time))
    return  inner

@timmer  # func = timmer(func)
def func():
    time.sleep(0.2)
    print('非常复杂')

#func = timmer(func)  # 执行timmer函数,将func函数名传给f。等到返回值inner函数名,所以func --> inner
func()
print("------------------ 5 -----------------------")

# 其他:被装饰函数带有参数
def timmer(f):
    def inner(*args, **kwargs):  # 函数的定义: * 聚合 args = (1,2,3,444,)
        start_time = time.time()
        f(*args, **kwargs)  # 函数执行: * 打散 f(*(1,2,3,4,5,6,))
        end_time = time.time()
        print('此函数耗时秒数 %s' % (end_time - start_time))
    return  inner

@timmer     # func = timmer(func)
def func(a, b):
    time.sleep(0.2)
    print('非常复杂 %s  %s ' % (a, b))

func('aaa', 'bbb')
print("------------------ 6 -----------------------")

# 其他:被装饰的函数要有返回值
def timmer(f):
    def inner(*args, **kwargs):
        start_time = time.time()
        ret = f(*args, **kwargs)
        end_time = time.time()
        print('此函数耗时秒数 %s' % (end_time - start_time))
        return ret
    return  inner

@timmer     # func = timmer(func)
def func(a, b):
    time.sleep(0.2)
    print('非常复杂 %s  %s ' % (a, b))
    return 666

ret = func('aaa', 'bbb')
print(ret)
print("------------------ 7 -----------------------")

# 装饰器常用格式
def wrapper(f):
    def inner(*args,**kwargs):
        """执行被装饰函数之前的操作"""
        ret = f(*args,**kwargs)
        """执行被装饰函数之后的操作"""
        return ret
    return inner

@wrapper
def func():
    print(333)

func()
print("------------------ 8 -----------------------")

# 装饰器小结
# 其实装饰器本质是闭包,他的传参,返回值都是借助内层函数inner,
# 他之所以借助内层函数inner 就是为了让被装饰函数 在装饰器装饰前后,没有任何区别。
# 看起来没有变化。

# 装饰器用途
# 登录认证,打印日志等等。给函数增加额外的功能,但是不能影响函数的执行方式,返回值等
# 日志
def wrapper(f):
    def inner(*args, **kwargs):
        print("记录日志开始")
        ret = f(*args, **kwargs)
        print("记录日志结束")
        return ret
    return inner

@wrapper
def func(a, b, name, age=18):
    print('我是被装饰的函数 %s %s' % (name, age))
    return a + b

ret = func(1, 2, name="tome")
print(ret)
print("------------------ 9 -----------------------")

# 登录认证
# 需求 三个页面需要登录才能访问,只要有一次登录成功就能访问
# flag = False
#
# def login():
#     username = input("账号>>>:")
#     password = input("密码>>>:")
#     if username == "alnk" and password == "123":
#         print('登录成功')
#         global flag
#         flag = True
#
# def auth(f):
#     def inner(*args,**kwargs):
#         # while 1:
#         if flag:
#             ret = f(*args,**kwargs)
#             return ret
#         else:
#             login()
#     return inner
#
# @auth
# def comment():
#     print('评论页面')
#
# @auth
# def artcle():
#     print('文章页面')
#
# @auth
# def dairy():
#     print('日记页面')
#
# comment()
# artcle()
# dairy()
# print("------------------ 10 -----------------------")

# 1.对扩展是开放的
# 为什么要对扩展开放呢?
# 我们说,任何一个程序,不可能在设计之初就已经想好了所有的功能并且未来不做任何更新和修改。
# 所以我们必须允许代码扩展、添加新功能。
#
# 2.对修改是封闭的
# 为什么要对修改封闭呢?
# 就像我们刚刚提到的,因为我们写的一个函数,很有可能已经交付给其他人使用了,
# 如果这个时候我们对其进行了修改,很有可能影响其他已经在使用该函数的用户
# 装饰器完美的遵循了这个开放封闭原则。

# 装饰器的进阶
# 1、正常情况下查看被装饰的函数的说明信息的方法在此处都会失效
# 解决办法
import time
from functools import wraps

def timmer(func):
    @wraps(func)  # 加在内层函数的正上方
    def inner(*args,**kwargs):
        start = time.time()
        ret = func(*args,**kwargs)
        print(time.time() - start)
        return ret
    return inner

@timmer
def index():
    """这是一个主页的信息"""
    time.sleep(0.5)
    print("from index")

index()
print(index.__doc__)
print("------------------ 11 -----------------------")

# 2、带有参数的装饰器
"""
假如你有成千上万个函数使用了一个装饰器,现在你想把这些装饰器都取消掉,你要怎么做?
一个一个的取消掉? 没日没夜忙活3天。
过两天你领导想通了,再让你加上。
"""
def outer(flag):
    # flag = True  # 装饰器开关
    def timmer(func):
        def inner(*args, **kwargs):
            if flag:
                print("""执行函数之前要做的""")
            ret = func(*args, **kwargs)
            if flag:
                print("""执行函数之后要做的""")
            return ret
        return inner
    return timmer

@outer(False)
def func():
    print(111)

func()
print("------------------ 12 -----------------------")

# 3、多个装饰器,装饰一个函数
def wrapper1(f):
    def inner(*args,**kwargs):
        print('我是装饰器1 开始')
        ret = f(*args,**kwargs)
        print("我是装饰器1 结束")
        return ret
    return inner

def wrapper2(f):
    def inner(*args,**kwargs):
        print('我是装饰器2 开头')
        ret = f(*args,**kwargs)
        print('我是装饰器2 结束')
        return ret
    return inner

@wrapper2
@wrapper1
def func():
    print("in func")

func()



#!/usr/bin/env python3
# author:Alnk(李成果)

# 可迭代对象:这个对象由多个元素组成,他就是可迭代的
# 这个对象内部只要含有"__iter__"方法,他就是可迭代的
for i in 'abc':
    print(i)

for i in [1, 2, 3]:
    print(i)

# for i in 1234:  # 数字是一个不可迭代对象
#     print(i)
print("-------------------- 1 -------------------------")

# int bool  ---- 不可迭代
# str list tuple dict set bytes range 文件句柄  --可以迭代

# 判断一个对象是否是可迭代的
# 方法一:内部是否有 "__iter__方法"
s1 = "tom"
print("__iter__" in dir(s1))  # True
n = 1
print("__iter__" in dir(n))  # False
print("__iter__" in dir(range))  # True

f = open('a.txt', encoding='utf-8', mode='w')
print("__iter__" in dir(f))  # True

# 方法二:
from collections import Iterable  # 判断一个对象是不是可迭代对象
l1 = [1, 2, 3]
print(isinstance(l1, Iterable))  # True
print("-------------------- 2 -------------------------")

# 迭代器:内部含有__iter__方法并且含有__next__方法的就是迭代器
# 如何判断此对象是不是迭代器?
# 方法1
l1 = [1,2,3]    # 不是迭代器
print('__iter__' in dir(l1))  # True
print('__next__' in dir(l1))  # False

#方法2
from collections import  Iterator
f = open('a.txt', encoding='utf-8', mode='w')     # 文件句柄是一个迭代器
# print("__iter__" in dir(f))  # True
# print("__next__" in dir(f))  # True
print(isinstance(f,Iterator))  # True
print("-------------------- 3 -------------------------")

# 迭代器和可迭代对象的区别
# 1、可迭代对象不能直接取值,必须转化成迭代器进行取值,把索引这个方法除外哈
l1 = [1, 2, 3]
for i in l1:  # for循环内部会把可迭代对象转化为迭代器,用__next__ 进行取值
    print(i)
print("-------------------- 4 -------------------------")

# 将一个可迭代对象转化为迭代器 iter()
l1 = [1, 2, 3]
obj = iter(l1)  # 迭代器
print(obj)
print(next(obj))
print(next(obj))
print(next(obj))
print("-------------------- 5 -------------------------")

# 迭代器有什么作用?
# 1,节省内存
# 2,一条路走到底,不反复
# 3,不易看出

# while语句模拟for循环去循环可迭代对象的机制
# 1,将可迭代对象转化成迭代器
# 2,利用next进行取值
# 3,利用异常处理停止循环
l1 = [1, 2, 3, 4, 5, 6]
# obj = l1.__iter__()  # 不建议用这种方法把可迭代对象转化为迭代器
obj = iter(l1)  # 转换成迭代器
while 1:
    # print(obj.__next__())   # 不建议用这种方法去取值
    try:
        print(next(obj))
    except:
        break



#!/usr/bin/env python3
# author:Alnk(李成果)

# 生成器:本质就是迭代器,自己可以通过代码写出来的迭代器
# 生成器的生成方式
# 1,函数式生成器
# 2,生成器表达式

# 函数式生成器
def func():
    # print(111)
    yield 5
    yield 6
    yield 7
    yield 8

g = func()  # 生成器对象
# 一个next对应一个 yield
print("a")
print(next(g))
print("b")
print(next(g))
print("c")
print(next(g))
print("d")
# print(next(g))
print("e")
print("--------------------- 1 ----------------------")

# 举例
def book():
    for i in range(1,501):
        print("python书籍 编号%s" % i)
# book()

def book_niu():
    for i in range(1,501):
        yield  "python书籍 编号%s" % i
gen = book_niu()

for i in range(50):
    print(next(gen))
print("--------------------- 2 ----------------------")
# 函数中只要有yield 他就不是函数了,他是生成器函数
# yield 与 return的区别
# return直接终止函数,yield不会终止函数。
# return给函数的执行者返回值,yield是给next(生成器对象)返回值。

# send
# send:不仅可以取值,还可以给上一个yield发送一个值
def f():
    a = 1
    b = 2
    count = yield a + b
    print(count)
    yield 5
    yield 6
    yield 7

g = f()
# send 与 next的区别
# 1、第一个 yield 不能用 send 取值
# print(g.send(1))
# print(next(g))
# print(next(g))
# print(next(g))
# print(next(g))

# print(next(g))
# print(g.send(None))
# print(g.send(None))
# print(g.send(None))
# print(g.send(None))

# 2、最后一个 yield 永远不会得到 send 发送的值
print(next(g))
print(g.send('a'))
print("--------------------- 3 ----------------------")

# yield from:将一个可迭代对象转化成了生成器返回
def func():
    l1 = ['李雷', 'tom', 'jerry', '小明']
    yield l1
g = func()
print(next(g))
print("--------------------- 4 ----------------------")

# yield from
def func():
    l1 = ['李雷', 'tom', 'jerry', '小明']
    yield from l1  # 将一个可迭代对象转化成了生成器返回
g = func()
print(next(g))
print(next(g))
print(next(g))
print(next(g))



#!/usr/bin/env python3
# author:Alnk(李成果)

# 生成器表达式 与 列表推导式非常类似
# 列表推导式         [   ]
# 生成器表达式       (   )

# 列表推导式: 用一行代码构建一个列表,列表推导式只能构建简单的或者比较复杂的列表
# 构建一个列表 [100以内所有的偶数],[0,2,4,6,8....100]
l1 = []
for i in range(0, 101, 2):
    l1.append(i)
print(l1)
print("------------------ 1 -----------------------------")

# 列表推导式分为两种模式:
# 1,循环模式  [变量(加工后的变量) for 变量 in iterable]
# 构建一个列表,[100以内所有的偶数]
print([i for i in range(0, 101, 2)])
print("------------------ 2 -----------------------------")

# [1,4,9,16,25,36,49]
print([i**2 for i in range(1, 8)])
print("------------------ 3 -----------------------------")

# ['a1', 'a2', .....'a20']
print([("a%s" % i) for i in range(1, 21)])
print("------------------ 4 -----------------------------")

# 2,筛选模式 [变量(加工后的变量) for 变量 in iterable if 条件]
# 30以内能被2整除的数的平方
print([i * i for i in range(1, 31) if i % 2 == 0])
print([i ** 2 for i in range(1, 31) if i % 2 == 0])
print("------------------ 5 -----------------------------")

# [1,2,3,4,6,7,8]
print([i for i in range(1, 9) if i != 5])
print("------------------ 6 -----------------------------")

# 过滤掉长度小于3的字符串列表,并将剩下的转换成大写字母
l1 = ['jerry', 'ba', 'aa', 'alnk']
print([i.upper() for i in l1 if len(i) > 3])
print("------------------ 7 -----------------------------")

# 将列表中的至少含有两个'e'的人名留下来。
names = [['Tom', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'], ['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer']]
# 方法1
l1 = []
for l in names:
    for name in l:
        if name.count('e') >= 2:
            l1.append(name)
print(l1)
print("------------------ 8 -----------------------------")

# 方法2
print([name for l in names for name in l if name.count("e") >= 2])
print("------------------ 9 -----------------------------")

# 生成器表达式:
# 优势:
# 1,一行搞定
# 2,节省内存
#
# 两种模式:
# 1,循环模式(变量(加工后的变量) for 变量 in iterable)
# (变量(加工后的变量) for 变量 in iterable if 条件)
#
#2,筛选模式(变量(加工后的变量) for 变量 in iterable if 条件)



#!/usr/bin/env python3
# author:Alnk(李成果)

# 匿名函数: 一句话函数 lambda

# 两个数相加
def func(a,b):
    return a + b

print(func(1, 3))
func(1, 3)

# 两个数相加
func1 = lambda x,y: x + y
print(func1(1, 2))

# 将 x, y 较大者返回
func2 = lambda x,y: x if x > y else y
print(func2(100,200))



#!/usr/bin/env python3
# author:Alnk(李成果)
# sum 求和
print(sum([i for i in range(101)]))
print(sum([i for i in range(101)], 100))
print("------------- 1 -----------------")

# min 可以加 key=函数 最小值
# max 可以加 key=函数 最大值
l1 = [3, 4, 1, 2, 7, -5]
print(min(l1))
print(max(l1))
print("------------- 2 -----------------")

l2 = [('a', 3), ('b', 2), ('c', 1)]
def func(x):
    return x[1]
print(min(l2, key=func))     # 注意这里min 会先把l2列表中的每个元素传递到func函数中去,然后在取最小的
print(max(l2, key=func))
# 改成lambda
print(min(l2, key=lambda x:x[1]))
print("------------- 3 -----------------")

# reversed 翻转 会生成一个迭代器
l1 = [i for i in range(10)]
print(l1)
from collections import Iterator
g =  reversed(l1)
print(isinstance(g,Iterator))
print(next(g))
print(next(g))
print(next(g))
print(next(g))
print("------------- 4 -----------------")

# sorted   排序
l1 = [1,2,8,7,5]
print(sorted(l1))

l2 = [('c',2),('b',3),('a',1)]
print(sorted(l2, key=lambda x:x[1]))  # 这个和min max 有点类似
print("------------- 5 -----------------")

# zip 拉链方法,会以最短的那个列表或其他的 去组合。生成一个迭代器
l1 = [1,2,3,4]
tu1 = ('a','b','c')
g = zip(l1,tu1)
print(next(g))
print(next(g))
print(next(g))
l1 = [1,2,3,4]
tu1 = ('a','b','c')
tu2 = ('a1','b1','c1')
g1 = zip(l1,tu1,tu2)      # 也可以多个元素组合
for i in g1:
    print(i)
print("------------- 6 -----------------")

# enumerate() 函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,
# 一般用在 for 循环当中。
l1 = ['a','b','c','d']
for index,i in enumerate(l1):
    print(index,i)
print("------------- 7 -----------------")

# abs() 函数返回数字的绝对值
print(abs(-1))
print(abs(1))
print("------------- 8 -----------------")

# all() 函数用于判断给定的可迭代参数 iterable 中的所有元素是否都为 TRUE,如果是返回 True,否则返回 False。
# 元素除了是 0、空、FALSE 外都算 TRUE
print( all('a') )
print( all([1,2,3,'',5,]) )
print("------------- 9 -----------------")

# any() 函数用于判断给定的可迭代参数 iterable 是否全部为 False,则返回 False,如果有一个为 True,则返回 True。
# 元素除了是 0、空、FALSE 外都算 TRUE
print( any(['',0,False]) )
print( any([1,0,False]) )
print("------------- 10 -----------------")

# bin() 返回一个整数 int 或者长整数 long int 的二进制表示 只能是数字
print(bin(100))
print("------------- 11 -----------------")

# bool() 函数用于将给定参数转换为布尔类型,如果没有参数,返回 False
print( bool(0) )
print( bool(1) )
print( bool('') )
print("------------- 12 -----------------")

# callable() 函数用于检查一个对象是否是可调用的。如果返回 True,object 仍然可能调用失败;
# 但如果返回 False,调用对象 object 绝对不会成功
print( callable(0) )
a = 1
print( callable(a) )
def f():
    pass
print( callable(f) )
print("------------- 13 -----------------")

# chr() 用一个整数作参数,返回一个对应的字符 。对应的ascii码 。可以用于验证码
print( chr(97) )
print("------------- 14 -----------------")

# compile() 函数将一个字符串编译为字节代码。 慎用
s1 = "for i in range(10):print(i)"
f = compile(s1,'','exec')
exec(f)
print("------------- 15 -----------------")

# dict() 函数用于创建一个字典

# dir() 函数不带参数时,返回当前范围内的变量、方法和定义的类型列表
# 带参数时,返回参数的属性、方法列表
print(dir())
print(dir(str))
print("------------- 16 -----------------")

# divmod() 函数把除数和余数运算结果结合起来,返回一个包含商和余数的元组(a // b, a % b)
print( divmod(7,3) )
print("------------- 17 -----------------")

# eval() 函数用来执行一个字符串表达式,并返回表达式的值。
print( eval("3*7") )
print("------------- 18 -----------------")

# exec 执行储存在字符串或文件中的 Python 语句,相比于 eval,exec可以执行更复杂的 Python 代码。
exec( 'print("hello world")' )
print("------------- 19 -----------------")

# filter() 函数用于过滤序列,过滤掉不符合条件的元素,返回一个迭代器对象,如果要转换为列表,可以使用 list() 来转换
# 该接收两个参数,第一个为函数,第二个为序列,序列的每个元素作为参数传递给函数进行判,
# 然后返回 True 或 False,最后将返回 True 的元素放到新列表中
l1 = [1,2,3,4,5,6,7,8,9,10,]
# def is_odd(n):
#     return n % 2 == 1
g = filter(lambda x:x%2==1, l1)
for i in g:
    print(i)
print("------------- 20 -----------------")

# float() 函数用于将整数和字符串转换成浮点数
print( float(1) )
print( float("100") )
print("------------- 21 -----------------")

# format() 格式化输出函数

# frozenset() 返回一个冻结的集合,冻结后集合不能再添加或删除任何元素
a = frozenset(range(10))
print(a)
print("------------- 22 -----------------")

# globals() 函数会以字典类型返回全部全局变量
def f():
    name = 'tom'
    print("1", globals())
print("2", globals())
f()
print("------------- 23 -----------------")

# hash() 用于获取取一个对象(字符串或者数值等)的哈希值
print(hash('abc1'))
print("------------- 24 -----------------")

# help() 函数用于查看函数或模块用途的详细说明
print(help('sys'))
print(help('str'))
print("------------- 25 -----------------")

# hex() 函数用于将一个指定数字转换为 16 进制数
print( hex(10) )
print("------------- 26 -----------------")

# id() 函数用于获取对象的内存地址
s = 'a'
print( id(s) )
print("------------- 27 -----------------")

# input() 函数接受一个标准输入数据,返回为 string 类型

# int() 函数用于将一个字符串或数字转换为整型
print( int("10") )
print( int(10.1) )
print("------------- 28 -----------------")

# isinstance() 函数来判断一个对象是否是一个已知的类型,类似 type()
a = 2
print( isinstance(a,int) )
s = 'alnk'
print( isinstance(s, str))
print("------------- 29 -----------------")

# iter() 函数用来生成迭代器
l1 = [1,2,3,4,]
print(type(l1))
g1 = iter(l1)
print(type(g1))
print("------------- 30 -----------------")

# len() 方法返回对象(字符、列表、元组等)长度或项目个数
print( len('abc'))
print("------------- 31 -----------------")

# list() 方法用于将 元组或字符串或迭代器 转换为列表
t1 = (1,2,3,)
print( list(t1))

s1 = "abcd"
print(list(s1))

g1 = (i for i in range(1,10))
print(type(g1))
print(list(g1))
print("------------- 32 -----------------")

# locals() 函数会以字典类型返回当前位置的全部局部变量
name = 'alnk'
def f():
    age = 12
    print(locals())
f()
print(locals())
print("------------- 33 -----------------")

# map() 会根据提供的函数对指定序列做映射
def squ(x):
    return x ** 2
l1 = [1,2,3,4,5]
# g = map(squ,l1)
g = map(lambda x:x**2,l1)
print(type(g))  # <class 'map'>
for i in g:
    print(i)
print("------------- 34 -----------------")

# next() 返回迭代器的下一个项目

# oct() 函数将一个整数转换成8进制字符串
print( oct(10))
print("------------- 35 -----------------")

# open() 方法用于打开一个文件,并返回文件对象

# ord() 函数是 chr() 函数(对于 8 位的 ASCII 字符串)的配对函数,
# 它以一个字符串(Unicode 字符)作为参数,返回对应的 ASCII 数值,或者 Unicode 数值
print( ord('a'))
print( chr(97))
print("------------- 36 -----------------")

# pow() 方法返回 xy(x的y次方) 的值。
print( pow(2,3))
print("------------- 37 -----------------")

# print() 方法用于打印输出,最常见的一个函数
print('abcd',end='|')
print(1234)
print('ABCD',end='')
print('efgh')
print("------------- 38 -----------------")

# range() 函数返回的是一个可迭代对象(类型是对象),而不是列表类型, 所以打印的时候不会打印列表

# repr() 函数将对象转化为供解释器读取的形式
s = "abcd"
print( repr(s))
dic = {'runoob': 'runoob.com', 'google': 'google.com'}
print(repr(dic))
print("------------- 39 -----------------")

# round() 方法返回浮点数x的四舍五入值
print( round(70.23456, 4))
print( round(70.23456, 0))
print( round(70.23456))
print("------------- 40 -----------------")

# set() 函数创建一个无序不重复元素集,可进行关系测试,删除重复数据,还可以计算交集、差集、并集等
l = [1,1,2,2,3,3]
s = set(l)
print(s)
print("------------- 41 -----------------")

# str() 函数将对象转化为适于人阅读的形式
f = 3.14
s = str(f)
print(type(f))
print(s, type(s))
print("------------- 42 -----------------")

# tuple 函数将列表转换为元组
l = [1,2,3]
t = tuple(l)
print(type(t))
print("------------- 43 -----------------")

# type() 函数如果你只有第一个参数则返回对象的类型
a = 1
print(type(a))
print("------------- 44 -----------------")

# 和类相关的内置函数
# classmethod() 学习类以后再来补充
# delattr() 学习类以后再来补充
# getattr() 学习类以后再来补充
# hasattr() 学习类以后再来补充
# issubclass() 学习类以后再来补充
# property()  学习类以后再来补充
# setattr() 学习类以后再来补充
# staticmethod() 学习类以后再来补充
# super() 学习类以后再来补充



#!/usr/bin/env python3
# author:Alnk(李成果)

# 1、整理装饰器的形成过程,背诵装饰器的固定格式
# 形成过程
# 第一版:写一个功能测试其他同事的函数执行效率
# 第二版:函数实现这个功能
# 第三版:在不改变函数的执行方式下,同时测试执行效率
# 第四版:装饰器雏形
# 第五版:装饰器雏形的优化,语法糖@
# 其他:被装饰函数带有参数
# 其他:被装饰的函数要有返回值
# 固定格式
def wrapper(func):
    def inner(*args, **kwargs):
        """执行被装饰函数之前的操作"""
        ret = func(*args, **kwargs)
        """执行被装饰函数之后的操作"""
        return ret
    return inner
print("------------- 1 ------------------")

# 2、编写装饰器,在每次执行被装饰函数之前打印一句 '每次执行被装饰函数之前都得先经过这里,这里根据需求添加代码'
def wrapper(func):
    def inner(*args, **kwargs):
        print('每次执行被装饰函数之前都得先经过这里,这里根据需求添加代码')
        result = func(*args, **kwargs)
        return result
    return inner

@wrapper
def f1(a):
    print('in f1 参数[%s]' % a )

f1(1111111)
print("------------- 2 ------------------")

# 3、编写装饰器,在每次执行被装饰函数之前让用户输入用户名,密码,给用户三次机会,登录成功之后,才能访问该函数
def auth(func):
    def inner(*args,**kwargs):
        count = 0
        while count < 3:
            username = input("请输入用户名>>>:").strip()
            password = input("请输入密码>>>:").strip()
            if username == "alnk" and password == "123":
                print('登陆成功!\n')
                result = func(*args, **kwargs)
                return result
            else:
                print("账号或者密码错误!")
                count += 1
    return inner

@auth
def func1():
    print('恭喜访问func1函数')

func1()
print("------------- 3 ------------------")

# 4、编写装饰器,为多个函数加上认证的功能(用户的账号密码来源于文件,只支持单用户的账号密码,给用户三次机会),
# 要求登录成功一次,后续的函数都无需再输入用户名和密码
flag = False
count = 0

def auth(func):
    def inner(*args,**kwargs):
        with open('user_info', encoding='utf-8', mode='r') as f:
            user_list = f.readline().strip().split('|')

        # 文件存储的账号密码
        name = user_list[0]
        pwd = user_list[1]

        global count
        while count < 3:
            username = input("请输入用户名>>>:").strip()
            password = input("请输入密码>>>:").strip()
            if username == name and password == pwd:
                print('登陆成功!')
                global flag
                flag = True
                count = 3  # 登录成功一次以后,后续就不需要在登录,不再进入while循环
                break
            else:
                print('账号或者密码错误')
                count += 1

        if flag:
            ret = func(*args,**kwargs)
            return ret

    return inner

@auth
def f1():
    print('in f1 ')

@auth
def f2():
    print('in f2 ')

@auth
def f3():
    print('in f3 ')

f1()
f2()
f3()
print("------------- 4 ------------------")

# 5、编写装饰器,为多个函数加上认证的功能(用户的账号密码来源于文件,可支持多账号密码),
# 要求登录成功一次(给三次机会),后续的函数都无需再输入用户名和密码。
import os

flag = False

def login():
    username = input("请输入用户名>>>:").strip()
    password = input("请输入密码>>>:").strip()

    if os.path.exists('user/%s' % username):    # 判断是否存在以用户名命名的文件
        with open('user/%s' % username,encoding='utf-8',mode='r') as f:
            user_list = f.readline().strip().split('|')
        name = user_list[0]
        pwd = user_list[1]

        if username == name and password == pwd:
            print('登陆成功!')
            global flag
            flag = True
        else:
            print('账号或者密码错误')
    else:
        print('账号或者密码错误')

def auth(func):
    def inner(*args,**kwargs):
        count = 0
        while count < 3:
            if flag:
                ret = func(*args,**kwargs)
                return ret
            else:
                login()
                count += 1
    return inner

@auth
def f1():
    print('in f1 ')

@auth
def f2():
    print('in f2 ')

@auth
def f3():
    print('in f3 ')

f1()
f2()
f3()
print("------------- 5 ------------------")

# 6、给每个函数写一个记录日志的功能,
# 功能要求:每一次调用函数之前,要将函数名称,时间节点记录到log的日志中
# 所需模块:
# import time
# struct_time = time.localtime()
# print(time.strftime("%Y‐%m‐%d %H:%M:%S",struct_time))
#
import time

def write_log(func_name,time_node):
    with open('log.txt',encoding='utf-8',mode='a') as f:
        f.write("函数名:[%s] 时间:[%s]\n" % (func_name,time_node) )

def wrapper(func):
    def inner(*args,**kwargs):
        # 获取时间戳
        struct_time = time.localtime()
        time_node = time.strftime("%Y-%m-%d %H:%M:%S",struct_time)
        # 获取被装饰的函数名
        func_name = func.__name__
        # 调用日志函数
        write_log(func_name,time_node)
        res = func(*args,**kwargs)
        return res
    return inner

@wrapper
def f1():
    time.sleep(4)
    print('in f1')

@wrapper
def f2():
    time.sleep(10)
    print('in f2')

@wrapper
def f3():
    time.sleep(5)
    print('in f3')

f1()
f2()
f3()



#!/usr/bin/env python3
# author:Alnk(李成果)

"""
需求:
1),启动程序,首页面应该显示成如下格式:
    欢迎来到博客园首页
    1:请登录
    2:请注册
    3:文章页面
    4:日记页面
    5:评论页面
    6:收藏页面
    7:注销
    8:退出程序
2),用户输入选项,3~6选项必须在用户登录成功之后,才能访问成功
3),用户选择登录,用户名密码从register文件中读取验证,三次机会, 没成功则结束整个程序运行,成功之后,可以选择访问3~6项,
    访问页面之前, 必须要在log文件中打印日志,日志格式为-->用户:xx 在xx年xx月xx日 执行了 %s函数,
    访问页面时,页面内容为:欢迎xx用户访问评论(文章,日记,收藏)页面
4),如果用户没有注册,则可以选择注册,注册成功之后,可以自动完成登录,然后进入首页选择。
5),注销用户是指注销用户的登录状态,使其在访问任何页面时,必须重新登录。
"""
import datetime

# 标志位
flag = False

# 用户名
user_name = None

def r_w_register(*args, mode='r'):
    """
    注册、获取用户账号密码信息
    :param args: 注册时,接收用户名和密码
    :param mode: 默认r 模式读取,a 模式注册
    :return: r模式返回用户信息字典{"name":"password",}  a模式返回True
    """
    if mode == 'r':
        user_dic = {}
        with open('register', encoding='utf-8', mode='r') as f:
            for line in f:
                l1 = line.strip().split('|')
                user_dic[l1[0]] = l1[1]
        return user_dic
    elif mode == 'a':
        if args:
            # 获取参数传递过来的需要注册的账号和密码
            user_name = args[0]
            user_pwd = args[1]
            # 获取已经注册的用户信息
            user_dic = r_w_register(mode='r')
            # 判断账号是否已经注册
            if not user_dic.get(user_name):
                with open('register', encoding='utf-8', mode='a') as f:
                    f.write('%s|%s\n' % (user_name,user_pwd) )
                    f.flush()
                return True
            else:
                print('[%s] 用户已经被注册了哦!\n' % user_name )
        else:
            print('请输入用户名和密码哦!\n')
    else:
        return '参数有误!\n'

def login():
    """登录"""
    # 获取用户帐号密码信息
    user_dic = r_w_register(mode='r')
    # 密码输错3次退出程序
    count = 0
    while count < 3:
        global user_name
        user_name = input('请输入账号>>>:')
        user_pwd = input('请输入密码>>>:')
        # 判断账号密码是否正确
        if user_dic.get(user_name) and user_dic[user_name] == user_pwd:
            print('恭喜,登录成功!\n')
            global flag
            flag = True
            break
        else:
            print('账号或者密码错误!\n')
            count += 1
        if count == 3:
            exit('密码错误次数过多,程序结束运行!')

def auth(func):
    """装饰器"""
    def inner(*args,**kwargs):
        while 1:
            if flag:
                # 日志记录
                func_name = func.__name__
                write_log(user_name, func_name)
                res = func(*args,**kwargs)
                return res
            else:
                login()
    return inner

def register():
    """注册"""
    global user_name
    user_name = input('请输入你要注册的账号>>>:')
    user_pwd = input('请输入你要注册的密码>>>:')
    # 注册时账号密码不能为空
    if len(user_name) == 0 or len(user_pwd) == 0:
        print('用户名和密码不能为空!\n')
    else:
        # 调用函数注册,获取返回值
        ret = r_w_register(user_name, user_pwd, mode='a')
        # 判断注册是否成功
        if ret:
            global flag
            flag = True
            print('[%s] 用户注册成功!\n' % user_name )
        else:
            print('注册失败!\n')

def write_log(user_name, func_name):
    """日志记录"""
    # 获取当前时间
    time = datetime.datetime.now()
    year = time.year
    month = time.month
    day = time.day
    content = "用户:[%s] 在 %s 年 %s 月 %s 日,执行了 [%s] 函数\n" % (user_name, year, month, day, func_name)
    # 记录日志
    with open('log', encoding='utf-8', mode='a') as f:
        f.write(content)
        f.flush()

@auth
def article():
    """文章页面"""
    print('欢迎 [%s] 用户访问文章页面\n' % user_name)

@auth
def diary():
    """日记页面"""
    print('欢迎 [%s] 用户访问日记页面\n' % user_name )

@auth
def comment():
    """评论页面"""
    print('欢迎 [%s] 用户访问评论页面\n' % user_name)

@auth
def colle():
    """收藏页面"""
    print('欢迎 [%s] 用户访问收藏页面\n' % user_name )

def log_out():
    """注销"""
    if user_name:
        global flag
        flag = False
        print('[%s] 账号注销成功!\n' % user_name )
    else:
        print('您没有登录哦,不用注销!\n')

def sign_out():
    """退出"""
    exit('退出程序!\n')

def view():
    """显示"""
    msg = '''------ 欢迎来到博客园首页 ------
    1:请登录
    2:请注册
    3:文章页面
    4:日记页面
    5:评论页面
    6:收藏页面
    7:注销
    8:退出程序
    '''
    dic = {
        '1':login,
        '2':register,
        '3':article,
        '4':diary,
        '5':comment,
        '6':colle,
        '7':log_out,
        '8':sign_out,
    }
    while 1:
        print(msg)
        choice = input('请输入编号>>>:')
        if dic.get(choice):
            dic[choice]()
        else:
            print('请输入正确的标号哟\n')

if __name__ == '__main__':
    view()