一个完整的闭包要满足三个条件:
函数中嵌套一个函数;
外层函数返回的是内层函数的函数名;
内层函数有引用外层函数的一个非全局变量;
def func1(x,y): num = 66 def func2(): print(x) print(y) print(num * 2) return func2每个函数都有一个__closure__,上面的闭包函数中的x,y都存在这个属性里
如:res = func1(99,"python"),打印print(res.__closure__),得到的结果是一个元组,里面两个元素,一个int类型,一个str类型;
闭包的作用:实现内部数据的锁定,提高稳定性;
1、开放封闭原则:软件实体应该是可扩展,而不可修改的,也就是说,对扩展是开放的,而对修改时封闭的;
2、装饰器的作用:在不更改原功能函数内部代码,并且不改变调用方法的情况下为原函数添加新的功能;
装饰器的应用场景:
登录验证:
函数运行时间统计;
执行函数之前做准备工作;
执行函数之后做清理工作;
这是一个登录的装饰器,调用首页的函数时,会先执行login函数进行登录验证,然后才执行index函数里面的代码,其中就是@login,这一行代码起的作用,
@login 相当于 index = login(index),而调用首页函数的代码,index()== login(index());
装饰器原理:将被装饰的函数当做一个参数传入到装饰器中,并且让被装饰的函数名指向装饰器内部的函数,在装饰器的内部函数中用接收到的参数再调用被装饰的函数;
带参数的装饰器和通用装饰器类似,只是把要传的参数放到装饰器的内层函数中,再通过传入装饰器中的函数调用即可;
装饰器装饰类的时候,装饰器内部一定要加return,因为要有一个接收对象来创建实例,如果没有加return,则UD打印出来就为None,而装饰器装饰函数时不是必须要加return
通过执行结果我们可以发现,多个装饰器装饰时,装饰的过程是从下往上装饰的,执行的顺序是从上往下执行的,其中:@login相当于updateinfo = login(updateinfo),
这时的updateinfo指向的是login装饰器的func_login函数,而@get_time则相当于updateinfo = get_time(updateinfo),这时的updateinfo则指向的是func_gettime函数,
因此:
updateinfo("天涯","18") = get_time(login(updateinfo("天涯","18")))
@classmethod
class MyClass: @classmethod def add(cls): print("add方法的cls:",cls) def sub(self): print("sub方法的self:",self) mc = MyClass() mc.add() mc.sub()MyClass.add() 打印结果为: add方法的cls: <class '__main__.MyClass'> sub方法的self: <__main__.MyClass object at 0x00AC32B0> add方法的cls: <class '__main__.MyClass'>通过打印结果,我们可以发现,类里面的方法被@classmethod装饰器装饰之后,就变成了类方法,这时的add方法既能被实例调用,也能被类调用,而实例方法sub(),
只能被实例调用,不能被类调用;
根据编写代码规范,类方法里面用cls表示类本身,而实例方法里面用self表示实例本身;
@staticmethod
class MyClass: @staticmethod def add(self): print("add方法是一个静态方法") def sub(self): print("sub方法的self:",self) mc = MyClass() mc.add("static") 运行结果: add方法是一个静态方法 Traceback (most recent call last): File "C:/Users/Administrator/PycharmProjects/untitled/cekai005_lei_01.py", line 118, in <module> mc.add() TypeError: add() missing 1 required positional argument: 'self'通过打印结果,我们可以发现,类里面的方法被@staticmethod装饰器装饰之后,就变成了静态方法,这时,不在需要传类本身代表的cls或者传实例本身代表的self参数,
而如果传入self或者cls,则会被当成位置参数,调用时需要传位置参数,不然会报错;
静态方法可被类调用,也可被实例调用;
@property
class MyClass: @property def add(self): print("add方法被property装饰器装饰后,可以像属性一样被调用") return "property" def sub(self): print("sub方法的self:",self) mc = MyClass() print(mc.add) 执行结果为: add方法被property装饰器装饰后,可以像属性一样被调用 property通过打印结果,我们可以发现,类里面的方法被@property装饰器装饰之后,可以当做实例属性一样被实例调用;
@property装饰器的作用是对被装饰的方法设置只读属性,被装饰的方法的返回值不能被修改,修改会报错;
用类实现装饰器,必须搭配__init__方法使用,__init__方法还要生成一个可供传入的func函数,再定义__call__方法调用func函数来实现类装饰器;
转载于:https://www.cnblogs.com/lzh501/p/10878934.html
相关资源:数据结构—成绩单生成器