python3 闭包、类的装饰器,元类
1.闭包
(1)一个函数里面还嵌套了函数;
(2)包含了对外部函数作用域中变量的引用
内部函数包含对外部作用于而不是全局作用域变量的引用,那么我们就称该内部函数为闭包函数;
作用:能够引用外部函数的变量,并且可以保证外部函数的变量控制在一个局部作用域;
和 函数还是有区别的。
def test():
sum=100
# 在函数内部定义一个桉树,并且里面的函数用到了外边函数的变量,那么将这个函数以及用到的一些变量称之为闭包
def test1(y):
return sum+y
# 这里返回的就是闭包的结果
return test1
t=test()
# 这里的5其实是给参数y
print(t(5))
#####################
105
nonlocal访问、修改外部函数的局部变量(python3)
是闭包内部变量的声明:声明变量不是局部变量,这样下方的代码可以对外部函数传入的变量进行修改
x=300
def test3():
x=200
print("————2————:%d" %x)
def test4():
nonlocal x
print("————3————:%d" %x)
x=100
print("————4————:%d" %x)
return test4
print("——1——%d" %x)
print("我是华丽分割线==========================")
t1=test3()
t1()
##################
——1——300
我是华丽分割线==========================
————2————:200
————3————:200
————4————:100
闭包和函数的区别:(面试经常问)
原文:https://blog.csdn.net/gymaisyl/article/details/83019368
闭包:在闭包中,既有函数,又有数据,而且数据是闭包里面独有的数据,与外界无影响;
函数:函数中,需要使用的全局变量,在一定程度上是受到限制的,因为全局变量不仅仅是一个函数使用,其他的函数也可能会使用到,一旦修改会影响到其他函数使用全局变量,所以全局变量不能随便修改从而在函数的使用中受到一定局限性。
2.装饰器
def outer(func): def inner(): print('我是 inner函数!!!') return inner #return inner() 这两种的差别 def foo(): print('我是原始函数!!!') outer(foo) outer(foo()) # 函数名: foo、outer、inner # 函数体:函数的整个代码结构 # 返回值: return后面的表达式 # 函数的内存地址:id(foo)、id(outer)等等 # 函数名加括号:对函数进行调用,比如foo()、outer(foo) # 函数名作为参数: outer(foo)中的foo本身是个函数,但作为参数被传递给了outer函数 # 函数名加括号被当做参数:其实就是先调用函数,再将它的返回值当做别的函数的参数,例如outer(foo()) # 返回函数名:return inner # 返回函数名加括号:return inner(),其实就是先执行inner函数,再将其返回值作为别的函数的返回值。
写代码要遵循开放封闭原则,简单来说,已经实现的功能代码内部不允许被修改,但外部可以被扩展。
上面的这句话就是说明使用装饰器的原因了。我自己认为的。
装饰器本质就是一个函数去装饰另外一个函数,可以在不修改原有代码的情况下,为被装饰的对象增加新的功能或者附加限制条件或者帮助输出;
高阶函数+嵌套=装饰器;
装饰器的存在就是给另外一个函数添加功能,不能修改被装饰函数的源代码;并且不能修改被装饰函数的调用方式。
一个理解:
函数即"变量"——函数名相当于变量名,函数体也就是变量值。
def outer(func): def inner(): print("认证成功!") result = func() print("日志添加成功") return result return inner @outer def f1(): print("业务部门1数据接口......") f1() 程序开始运行,从上往下解释,读到def outer(func):的时候,发现这是个“一等公民”函数,于是把函数体加载到内存里,然后过。 读到@outer的时候,程序被@这个语法糖吸引住了,知道这是个装饰器,按规矩要立即执行的,于是程序开始运行@后面那个名字outer所定义的函数。 程序返回到outer函数,开始执行装饰器的语法规则。规则是:被装饰的函数的名字会被当作参数传递给装饰函数。装饰函数执行它自己内部的代码后,会将它的返回值赋值给被装饰的函数。原来的f1函数被当做参数传递给了func,而f1这个函数名之后会指向inner函数。 看看以下两种区别: def outer(func): def inner(): print("认证成功!") result = func() print("日志添加成功") return result return inner @outer def f1(): print("业务部门1数据接口......") f1() print('===========================================') def outer(func): print("认证成功!") result = func() print("日志添加成功") return result @outer def f2(): print("业务部门1数据接口......")
简单装饰器:
对没有参数,没有返回值的函数进行装饰:
def set_func(func):
def call_func():
print("---这是添加功能1----")
print("---这是添加功能2----")
func()
return call_func
@set_func
def test():
print("----这个是主功能---")
test()
######################
---这是添加功能1----
---这是添加功能2----
----这个是主功能---
装饰器简单运用:
import time
def set_func(func):
def call_func():
start_time=time.time()
func()
stop_time=time.time()
print("alltime:%f" % (stop_time-start_time))
return call_func
@set_func #等价于test=set_func(test)
def test():
print("---test---")
time.sleep(2)
test()
######################
---test---
alltime:2.000812
对有参数,无返回值的函数进行修饰:
def set_func(func):
def call_func(num):
print("---这是添加功能1----")
print("---这是添加功能2----")
func(num)
return call_func
@set_func
def test(num):
print("----这个是主功能%d---" %num)
test(5)
---这是添加功能1----
---这是添加功能2----
----这个是主功能5---
同一个装饰器对多个函数进行装饰:
def set_func(func):
def call_func(num):
print("---这是添加功能1----")
print("---这是添加功能2----")
func(num)
return call_func
@set_func
def test1(num):
print("----这个是主功能%d---" %num)
@set_func
def test2(num):
print("----这个是主功能%d---" %num)
test1(5)
test2(20)
#########################
---这是添加功能1----
---这是添加功能2----
----这个是主功能5---
---这是添加功能1----
---这是添加功能2----
----这个是主功能20---
注意:
装饰器在调用函数之前,已经被python解释器执行了,所以要牢记 当调用函数之前 其实已经装饰好了,正常调用就可以了。
对使用不定长参数的函数进行修饰:
def set_func(func):
def call_func(num,*args,**kwargs):
print("---这是添加功能1----")
print("---这是添加功能2----")
func(num,*args,**kwargs)# 拆包
return call_func
@set_func
def test(num,*args,**kwargs):
print("----这个是主功能%d---" %num)
print("----这个是主功能---" ,args)
print("----这个是主功能---" ,kwargs)
test(20)
test(100,200)
test(20,50,300,mm="小猪猪")
#########
---这是添加功能1----
---这是添加功能2----
----这个是主功能20---
----这个是主功能--- ()
----这个是主功能--- {}
---这是添加功能1----
---这是添加功能2----
----这个是主功能100---
----这个是主功能--- (200,)
----这个是主功能--- {}
---这是添加功能1----
---这是添加功能2----
----这个是主功能20---
----这个是主功能--- (50, 300)
----这个是主功能--- {'mm': '小猪猪'}
对带有返回值的函数进行修饰:
def set_func(func):
def call_func(num,*args,**kwargs):
print("---这是添加功能1----")
print("---这是添加功能2----")
return func(num,*args,**kwargs)# 拆包
return call_func
@set_func
def test(num,*args,**kwargs):
print("----这个是主功能%d---" %num)
print("----这个是主功能---" ,args)
print("----这个是主功能---" ,kwargs)
return "hello,python 坚持坚持坚持,加油加油加油"
ret=test(20,50,300,mm="小猪猪")
print(ret)
#####################
---这是添加功能1----
---这是添加功能2----
----这个是主功能20---
----这个是主功能--- (50, 300)
----这个是主功能--- {'mm': '小猪猪'}
hello,python 坚持坚持坚持,加油加油加油
多个装饰器对同一个函数进行装饰:
这时,是从最下面的一个装饰器开始装饰,然后再往上。
def set_func1(func):
print("----开始进行添加功能1的操作")
def call_func(*args,**kwargs):
print("---这是添加功能(11)----")
print("---这是添加功能(12)----")
return func(*args,**kwargs)# 拆包
return call_func
def set_func2(func):
print("----开始进行添加功能2的操作")
def call_func(*args,**kwargs):
print("---这是添加功能(21)----")
print("---这是添加功能(22)----")
return func(*args,**kwargs)# 拆包
return call_func
@set_func1
@set_func2
def test(num,*args,**kwargs):
print("----这个是主功能%d---" %num)
return "每天比昨天多学习一点点,就会越来越优秀,加油"
ret=test(20,50,300,mm="小猪猪")
print(ret)
##############
----开始进行添加功能2的操作
----开始进行添加功能1的操作
---这是添加功能(11)----
---这是添加功能(12)----
---这是添加功能(21)----
---这是添加功能(22)----
----这个是主功能20---
每天比昨天多学习一点点,就会越来越优秀,加油


带有参数的装饰器:
def set_func_num(fun_num): def set_func(func): def call_func(*args,**kwargs): if fun_num==1: print("---要添加功能1----") elif fun_num==2: print("---要添加功能2----") return func(*args,**kwargs)# 拆包 return call_func return set_func @set_func_num(1) def test1(): print("----这个是主功能1---" ) @set_func_num(2) def test2(*args,**kwargs): print("----这个是主功能2---" ) test1() test2() ################ ---要添加功能1---- ----这个是主功能1--- ---要添加功能2---- ----这个是主功能2---



浙公网安备 33010602011771号