目录
闭包
在一个函数中访问另一个函数的内部变量,常见的形式是在一个函数中创建另一个函数,并且外部函数返回内部函数,例子如下:
test=cup("黑色")中的test=>water,函数名加上()可当做函数,这里的test("水")相当于water("水")
def cup(x):
def water(y):
print(x+"杯子装了"+y)
return water
test=cup("黑色")
test("水")
黑色杯子装了水
Process finished with exit code 0
闭包中修改外部变量
使用nonlocal 声明外部变量
根据上例修改如下:
def cup(x):
def water(y):
nonlocal x
x="白色"
print(x+"杯子装了"+y)
return water
白色杯子装了水
Process finished with exit code 0
装饰器
在不该变原有对象的基础上,给对象添加新的功能,使用了闭包
简单应用
(我们在perform函数处使用装饰器,增加了练习功能,这里函数名可作为参数传到装饰器类)
def practice(fn):
def inner():
print("请先练习")
fn()
return inner
def perform():
print("上台表演")
perform=practice(perform)
perform()
请先练习
上台表演
简化使用
(@practice相当于perform=practice(perform))
def practice(fn):
def inner():
print("请先练习")
fn()
return inner
@practice
def perform():
print("上台表演")
perform()
装饰带有参数的函数
(在内部函数填入对应参数即可,我在这里加了个number参数)内部函数相当于被装饰函数
def practice(fn):
def inner(number):
print("请先练习")
fn(number)
return inner
@practice
def perform(number):
print("上台表演",number,"次")
perform(1)
请先练习
上台表演 1 次
Process finished with exit code 0
装饰带有返回值的函数
(可以将inner当做perform函数,被装饰函数有参数有返回值,那我内层函数也得有)
def practice(fn):
def inner(number):
print("请先练习")
x=fn(number)
return x
return inner
@practice
def perform(number):
return number
print(perform("再上台表演"))
请先练习
再上台表演
Process finished with exit code 0
万能装饰器
def decorating(fn):
def inner(*args,**kwargs):
fn(*args,**kwargs)
print("简单装饰下吧")
return fn#有返回值也可以返回
return inner
@decorating
def decorated(*args,**kwargs):#可以传入任意数量形参
print(args,kwargs)
decorated(1,2,user="me")
(1, 2) {'user': 'me'}
简单装饰下吧
多个装饰器
def decorating1(fn):
def inner(*args,**kwargs):
fn(*args,**kwargs)
print("简单装饰下吧,这是第一个装饰器")
return fn#有返回值也可以返回
return inner
def decorating2(fn):
def inner(*args,**kwargs):
fn(*args,**kwargs)
print("简单装饰下吧,这是第二个装饰器")
return fn#有返回值也可以返回
return inner
#多个装饰器的写法,函数先被最靠近他的装饰器装饰
@decorating2
@decorating1
def decorated(*args,**kwargs):#可以传入任意数量形参
print(args,kwargs)
decorated(1,2,user="me")
(1, 2) {'user': 'me'}
简单装饰下吧,这是第一个装饰器
简单装饰下吧,这是第二个装饰器
装饰器传参
def people(peo):#装饰器传参需要在外部嵌套一个函数,和套娃相似
def outside(fn):
def inner(x):
print(peo+"喝",end="")
fn(x)
return inner
return outside
@people("小孩") #1、people("小孩") 2、@cup(water)
def water(x):
print(x)
water("热水")
小孩喝热水
类装饰器
(可以理解为__call__函数将 类变得和函数一样可以调用,这个函数可以类比函数装饰器的inner方法)
class Decorating():#默认参数为object
def __init__(self,fn):
self.fn=fn
def __call__(self, *args, **kwargs):#__call__方法将对象变得可以调用
for x in range(3):
self.fn()
@Decorating#decorate=Decorating(decorated)
def decorated():
print("test")
decorated()
test
test
test
@property装饰器
我们可以看到调用类的私有变量需要完整的调用函数,如果使用装饰器property就可以直接使用函数名来获取私有变量,方便了许多。下面两个列子效果一样
class Test():
def __init__(self,number):
self._number=number
def getage(self):
return self._number
test=Test(1)
print(test.getage())
class Test():
def __init__(self,number):
self._number=number
@property
def getage(self):
return self._number
test=Test(1)
print(test.getage)
1