VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > temp > python爬虫 >
  • python函数知识七 闭包、装饰器一(入门)、装饰器二(进阶)

21.闭包

  1. 闭包:在嵌套函数内,使用非全局变量(且不使用本层变量)
  2. 闭包的作用:1.保证数据的安全性(纯洁度)。2.装饰器使用
  3. .__closure__判断是否是闭包
def func():
    a = 1 
    def foo():
        print(a)
    return foo
ret = func()
ret()
#例子
def func():
    avg_lst = []
    def foo(pirce):
        avg_lst.append(pirce)
        avg = sum(avg_lst) / len(avg_lst)
        return avg
    return foo
ret = func()
print(ret(1500))
print(ret(1600))
print(ret.__closure__)#结果:(<cell at 0x000002095400B558: list object at 0x00000209540A5B48>,)证明是闭包
print(func.__closure__)#结果:None,不是闭包

print(ret.__code__.co_freevars)#获取的是自由变量
print(ret.__code__.co_varnames)#获取的是局部变量

22.装饰器一(入门)

1.一个装饰器装饰多个函数

开放封闭原则:扩展是开放的(增加新功能),源码是封闭的(修改已经实现的功能)

作用:在不改变源代码及调用方式的基础下额外增加新功能。

装饰器:用来装饰的工具

2.版一:
import time
start_time = time.time
def func():
    time.sleep(2)#睡眠s模拟网络延时
    print("我要飞")
func()   
print(time.time - start_time)
#改变了源代码
3.版二:
def times(f):
    start_time = time.time()
    f()
    print(time.time() - start_time)
def foo():
    time.sleep(3)
    print("我飞的比你高")
#times(foo)#改变了调用方式
s = foo
foo = times
foo(s)#不改变调用方式
4.版三:(low版装饰器)
def times(f):
    def inner():
        start_time = time.time()
        f()
        print(time.time() - start_time)
    return inner
def foo():
    time.sleep(3)
    print("我飞的比你高")
foo = times(foo)
foo()
5.版四:
def wrapper(f):
    def inner(a):
        start_time = time.time()
        f(a)
        print(time.time() - start_time)
    return inner#切记不加括号

def func(a):
    print(f"{a}你不行")
func = wrapper(func)
func("alex")
#传输多个数据,用*args,**kwargs
6.版五(标准版装饰器):

@wrapper#语法糖:必须放在要装饰的函数的正上方

def wrapper(f):#f是要被装饰的函数名
    def inner(*args,**kwargs):
        "被装饰前"
        start_time = time.time()
        ret = f(*args,**kwargs)
        print(time.time() - start_time)
        "被装饰后"
        return ret
    return inner#切记不加括号
@wrapper#语法糖 -->func = wrapper(func)
def func(*args,**kwargs):
    print(f"{a}你不行")
    return "我可以返回了"
#func = wrapper(func)#有语法糖不用多次赋值
func("alex")

23.装饰器二(进阶)

1.有参装饰器:

​ 有参装饰器:在基础装饰器的基础上再套一层函数

#有参装饰器实现登陆验证
msg = """
QQ
微信
抖音
请输入您要登录的的app:
"""
chose = input(msg).upper()
dict_flag = {'username':None,'flag':False}
def auth(a):
    def wrapper(f):
        def inner(*args,**kwargs):
            if dic_flag['flag']:
                fun(*args,**kwargs)
            else:
                if argv =="QQ":
                    print("欢迎登陆QQ")
                    user = intput("user:")
                    pwd = input("passwd:")
                    if user == "alex" and pwd == "alex123":
                        dict_flag["flag"] = True
                        dict_flag["username"] = user
                        foo(*args,**kwargs)
                        
                    else:
                        print("用户名或密码错误!")
        return inner
    return wrapper
@auth(chose)
"""
语法糖拆分:
wrapper = auth(chose)
foo = wrapper(foo)
"""
def foo():
    print("这是被装饰的函数")
foo()

2.多个装饰器装饰一个函数:

​ 当被装饰的函数正上方有多个装饰器,先执行里被装饰函数最近的装饰器(小技巧:进入装饰器,从上往下,走到最后一个装饰器,执行被装饰的函数,退出装饰器从下往上)

def wrapper1(f):
    def inner1(*args,**kwargs):
        print("这是第一个装饰器开始")
        f(*args,**kwargs)
        print("这是第一个装饰器结束")
        return 
    return inner1

def wrapper2(f):
    def inner2(*args,**kwargs):
        print("这是第二个装饰器开始")
        f(*args,**kwargs)
        print("这是第二个装饰器结束")
        return 
    return inner2

@wrapper1
@wrapper2
"""
两个语法糖等价于:

foo = wrapper2(foo)#foo == inner2
foo = wrapper1(foo)#foo = wrapper(inner2),foo == inner1
foo()#-->inner1()
"""
def foo():
    print("这是被装饰的函数")
foo()
'''
结果:

这是第一个装饰器开始

这是第二个装饰器开始

这是被装饰的函数
这是第二个装饰器结束
这是第一个装饰器结束
'''

相关教程