变量名解析:LEGB原则
变量名查找:
首先从本地(L)查找;
本地没有找到,从上一层机构中的def或者lambda的本地作用域(E);
从全局作用域(G)中查找;
从内置的模块(B)中查找,第一个出现的地方查找;
nonlocal关键字:内部函数想要改变外部函数的变量,需要加nonlocal关键字,示例如下
def outer():a = 100def inner():nonlocal ab = 200a += bprint('我是内部函数', a)inner()print(a)outer()
首先看一下维基上对闭包的解释:
在计算机科学中,闭包(英语:Closure),又称词法闭包(Lexical Closure)或函数闭包(function closures),是引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外。所以,有另一种说法认为闭包是由函数和与其相关的引用环境组合而成的实体。闭包在运行时可以有多个实例,不同的引用环境和相同的函数组合可以产生不同的实例。
形成闭包的三个条件:
简单示例如下
'''
求直线上的对应x的y值,方程式:y = a*x+b
'''def outer(a, b):def inner(x):return a * x + breturn innerline = outer(2, 1)
print(line(1))
简单分析:通过断点查看
先看一段代码:自己思考结果
def my_func(*args):fs = []for i in range(3):def func():return i * ifs.append(func)return fsfs1, fs2, fs3 = my_func()
print(fs1())
print(fs2())
print(fs3())
结果会是0 1 4 吗?并不是 结果为 4 4 4,为什么呢?
正确的写法:
def my_func(*args):fs = []for i in range(3):func = lambda _i=i: _i * _ifs.append(func)return fsfs1, fs2, fs3 = my_func()
print(fs1())
print(fs2())
print(fs3())
总结:返回闭包中不要引用任何循环变量,或者后续会发生变化的变量。
参考文章:
因为还没有学习面向对象,这里关于类装饰器相关的内容暂时不介绍,只讲解光宇函数装饰器内容。
下面我们通过模拟新房装修来认识下装饰器,你买了一座新房子(毛坯房),现在我们要对毛坯房进行装修。
开闭原则是编程中最基础、最重要的设计原则。
基本介绍:
示例如下:
def decorator(func):def wrapper():func()print('刷漆')print('铺地板')print('买家具')print('精装修房,可以入住啦~~~')return wrapper@decorator
def house():print('毛坯房。。。')house()
那么执行顺序是怎么样的呢?
def decorator(func):print('decorator start ...')def wrapper():print('wrapper start ...')func()print('wrapper end ...')print('decorator end ...')return wrapper@decorator
def func():print('函数执行...')# func()
执行结果:
decorator start …
decorator end …
执行顺序:加载decorator -> 加载原始func->执行decorator->func此时指向wrapper
还是以上面装修房子为例,我们是装修队的,需要知道房屋地址。
def decorator(func):def wrapper(address):func(address)print('刷漆')print('铺地板')print('买家具')print('精装修房,可以入住啦~~~')return wrapper@decorator
def house(address):print('房子在: {}是一座毛坯房。。。'.format(address))house('杭州西湖')
随着业务拓展,我们不仅要装修房子,还要装修工厂,装修工厂的时候,我们还要知道厂房的面积。装修房子和装修工厂过程相似,只是接收的参数不同,那么我们能不能用相同的装饰器呢?
def decorator(func):def wrapper(*args):func(*args)print('刷漆')print('铺地板')print('买家具')print('精装修房,可以入住啦~~~')return wrapper@decorator
def house(address):print('房子在: {} 是一座毛坯房。。。'.format(address))@decorator
def factory(address, area):print('工厂在: {} 是一座毛坯房,建筑面积: {}'.format(address, area))house('杭州西湖')
factory('杭州西湖', 100)
同理,如果参数有默认值参数,那么形参需要加**kwargs:
def decorator(f):passdef wrapper(*args, **kwargs):passf(*args, **kwargs)passpassreturn wrapper
继续以装修房子为例,我们现在要对装修房子做一个预算,看看毛坯房+装修需要花费多少。
def decorator(f):def wrapper(*args, **kwargs):ret = f(*args, **kwargs)print('刷漆')print('铺地板')print('买家具')print('精装修房,可以入住啦~~~')ret += 10000return retreturn wrapper@decorator
def house(address, area):print('房子在: {}是一座毛坯房, 面积:{}'.format(address, area))return 50000cost = house('杭州西湖', 100)
print('预计花费:{}'.format(cost))
简单示例:
def decrator(*dargs, **dkargs):def wrapper(func):def _wrapper(*args, **kargs):print("装饰器参数:", dargs, dkargs)print("函数参数:", args, kargs)return func(*args, **kargs)return _wrapperreturn wrapper@decrator(1, 2, a=1, b=2)
def f():print('函数执行')f()
执行顺序:加载decorator->加载f->执行decorator->返回wrapper->执行wrapper->放回_wrapper,f指向_wrapper
一般装饰器参数很少使用。
def decorator_1(f):print('decorator_1 start')def wrapper(*args, **kwargs):print('wrapper_1 start')ret = f(*args, **kwargs)print('wrapper_1 end')return retprint('decorator_1 end')return wrapperdef decorator_2(f):print('decorator_2 start')def wrapper(*args, **kwargs):print('wrapper_2 start')ret = f(*args, **kwargs)print('wrapper_2 end')return retprint('decorator_2 end')return wrapper@decorator_2
@decorator_1
def hello():print('hello python')hello()
可以看到,当多个装饰器装饰同一个函数时,会是一个嵌套的装饰结果,也就是说,先执行完离函数近的一个装饰器,然后再用离函数远的装饰器来装饰执行结果。
装饰器功能:
通用函数装饰器格式:
def decorator(f):passdef wrapper(*args, **args):passret = f(*args, **args)passreturn retpassreturn wrapper
本文发布于:2024-02-02 14:46:23,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170685638444503.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |