装饰器
装饰器: 在不改变原有代码的基础上,实现功能的扩充.用原函数扩展新功能,用新功能去代替旧功能,用@表示
情况一: 基本用法(闭包函数),通过闭包函数来扩展新功能
def kuozhan(tree): def new_tree(): print("旁边有小草") tree() print("旁边有小花") return new_tree def tree(): print("一棵大树") tree = kuozhan(tree) tree() # 旁边有小草 # 一棵大树 # 旁边有小花
情况二:用@符号来表示装饰器,@符号自动把下面的函数传递给装饰器,把新函数返回,让新函数代替旧函数,以实现功能的扩充
def kuozhan(tree): def new_tree(): print("旁边有小草") tree() print("旁边有小花") return new_tree @kuozhan def tree(): print("一棵大树") tree() # 旁边有小草 # 一棵大树 # 旁边有小花
情况三:装饰器的嵌套
def kuozhan2(tree): def new_tree(): print("小草会长成草坪5") tree() print("小花会长成花卉4") return new_tree def kuozhan1(tree): def new_tree(): print("旁边有小草3") tree() print("旁边有小花2") return new_tree @kuozhan1 # 再到装饰器1,返回3,5,1,4,2 @kuozhan2 # 先到装饰器2,返回5,1,4 def tree(): print("一棵大树1") tree() # 旁边有小草3 # 小草会长成草坪5 # 一棵大树1 # 小花会长成花卉4 # 旁边有小花2
情况四:用装饰器修饰带有参数的函数,装饰器内的函数也需有一一对应的参数
def kuozhan(tree): def new_tree(name): print("{}旁边有小草".format(name)) tree(name) print("旁边有小花") return new_tree @kuozhan def tree(name): print("{name}有一棵大树".format(name=name)) tree("bob") # bob旁边有小草 # bob有一棵大树 # 旁边有小花
情况五:用装饰器修饰带有参数返回值的函数
def kuozhan(person): def new_person(*args,**kwargs): print("新学期的开始") lst = person(*args,**kwargs) print("大家加油") return lst return new_person @kuozhan def person(*args,**kwargs): list1 = ["bob","alice","jack"] for i in args: print("班主任是:"+i) return [(k,v) for k,v in kwargs.items() if k in list1 ] res = person("张三","李四",bob=18,alice=19,jack=20,lisa=21) print(res) # 新学期的开始 # 班主任是:张三 # 班主任是:李四 # 大家加油 # [('bob', 18), ('alice', 19), ('jack', 20)]
情况六:用类装饰器来拓展原函数
# 方式一: 用类.方法来调 class Kuozhan(): def kuozhan1(tree): print("大树旁边有小草") tree() print("大树旁边有小花") @Kuozhan.kuozhan1 def tree(): print("我是一颗大树") # 大树旁边有小草 # 我是一颗大树 # 大树旁边有小花 # 方式二: 直接用类()调,配合__call__方法 class Kuozhan(): def __call__(self,tree): return self.kuozhan2(tree) def kuozhan1(tree): print("大树旁边有小草") tree() print("大树旁边有小花") def kuozhan2(self,tree): print("小草长大成草坪") tree() print("小花长大成花卉") @Kuozhan() def tree(): print("我是一颗大树") # 小草长大成草坪 # 我是一颗大树 # 小花长大成花卉
情况七:带有参数的函数装饰器
def outter(num): def kuozhan(func): def new_tree(self): print("大树小的时候是小树") res = func(self) print("小树长大了是大树") return res def new_grass(self): print("小草小的时候是一棵草") res = func(self) print("小草长大了是草坪") return res if num == 1: return new_tree elif num == 2: return new_grass elif num == 3: return "我把flower方法变成了属性" return kuozhan class Plant(): @outter(1) def tree(self): print("我是一颗大树") @outter(2) def grass(self): print("我是一颗小草") @outter(3) def flower(self): print("我是一朵花") obj = Plant() obj.tree() # 大树小的时候是小树 # 我是一颗大树 # 小树长大了是大树 obj.grass() # 小草小的时候是一棵草 # 我是一颗小草 # 小草长大了是草坪 print(obj.flower) # 我把flower方法变成了属性
情况八:带有参数的类装饰器
class Kuozhan(): name = "大树" def __init__(self,num): self.num = num def __call__(self,cls): if self.num == 1: return self.new_func1(cls) elif self.num == 2: return self.new_func2(cls) def grass(self): print("大树旁边有小草") def new_func1(self,cls): def func1(): cls.name = Kuozhan.name cls.grass = Kuozhan.grass return cls() return func1 def new_func2(self,cls): def func2(): if "mytree" in cls.__dict__: res = cls.mytree() cls.mytree = res return cls() return func2 # 形式一: 为类添加方法或者属性 @Kuozhan(1) class Tree(): def mytree(): return "我是一颗大树" obj = Tree() print(obj.name) # 大树 obj.grass() # 大树旁边有小草 # 形式二: 将类的方法改为属性 @Kuozhan(2) class Tree(): def mytree(): return "我是一颗大树" obj = Tree() print(obj.mytree) # 我是一颗大树
面向对象中的方法: 普通方法,绑定方法,静态方法
class Tree(): #普通方法: 可以有参也可以无参,相当于普通的函数 def grow(): print("小树长成大树") # 绑定方法: (对象) 自动传递参数为对象 def green(self): print("大树有成片的绿叶子") # 绑定方法: (类) 自动传递参数为类 @classmethod def sing(cls): print(cls) print("风吹叶子的声音像唱歌") # 静态方法: 不管是对象还是类,都可以调用,默认不会传递任何参数 @staticmethod def air(): print("大树可以净化空气") obj = Tree() Tree.grow() # 小树长成大树 obj.green() # 大树有成片的绿叶子 绑定方法推荐用对象调 Tree.green(111) # 大树有成片的绿叶子 Tree.sing() # 绑定到类的方法推荐用类调 # <class '__main__.Tree'> # 风吹叶子的声音像唱歌 obj.sing() # <class '__main__.Tree'> # 风吹叶子的声音像唱歌 # 静态方法有参数时保证参数一一对应.在类外,为对象添加的方法都是静态方法 Tree.air() # 大树可以净化空气 obj.air() # 大树可以净化空气
porperty装饰器:
功能: 将方法变成属性使用,自动触发
作用: 控制属性的获取(@property),设置(@属性名.setter),删除(@属性名.deleter)操作
意义: 间接增加成员的安全性,可以通过自定义逻辑对成员进行控制
# 方式一: 使用相同的名称 class Myname(): def __init__(self,name): self.name = name # 获取属性 @property def username(self): return self.name #设置属性 @username.setter def username(self,strval): self.name = strval #删除属性 @username.deleter def username(self): pass obj = Myname("bob") print(obj.name) #bob 自动触发property obj.name = "alice" print(obj.name) #alice 自动触发设置方法,strval接收alice del obj.username print(obj.name) # alice 因为自动触发的删除属性,阻止了删除 # 方式二: class Myname(): def __init__(self,name): self.name = name # 获取属性 @property def get_username(self): return self.name #设置属性 def set_username(self,strval): self.name = strval #删除属性 def del_username(self): pass username = property(get_username,set_username,del_username) obj = Myname("bob") print(obj.name) # bob obj.name = "jack" print(obj.name) # jack del obj.username print(obj.name) # jack