[TimLinux] Python 装饰器
Posted TimLinux
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[TimLinux] Python 装饰器相关的知识,希望对你有一定的参考价值。
1. 装饰器
- 一种语法格式,用于替换另外一个编码风格,一种语法糖,通过语法结构明确标识出这样一种语法。
- 自动在被装饰对象尾部执行代码(不使用装饰器语法时,需要明确写明的代码)
- 被装饰对象可以为函数、类,被装饰对象为函数(则定义装饰器为函数装饰器),被装饰对象为类(则定义装饰器为类装饰器)
- 装饰器自身可以是函数、类。
2. 函数装饰器
函数装饰器自动添加的代码:
+----------------------------+----------------------------+ | @decorator | def func(): | | def func(): | .... | | .... | func = decorator(func) | +----------------------------+----------------------------+ | func() | decorator(func)() | +----------------------------+----------------------------+
2.1. 装饰器实现
2.1.1. 函数方式实现
def decorator(F): def tmp_F(*args_for_F): 这个函数内可以添加任你想执行的代码。 F(*args_for_F) return tmp_F # 这个返回的是函数地址
2.1.2. 类方式实现
class decorator: def __init__(self, F): self.__func = F def __call__(self, *args_for_F): self.__func(*args_for_F) * 注意:这个方式,被装饰对象如果是类中的函数,则不能正常工作,self的含义发生了变化。
3. 类装饰器
类装饰器自动添加的代码:
+----------------------------+----------------------------+ | @decorator | class C: | | class C: | .... | | .... | C = decorator(C) | +----------------------------+----------------------------+ | C() | decorator(C)() | +----------------------------+----------------------------+
3.1. 装饰器实现
3.1.1. 函数方式实现
def decorator(cls): class tmp_C: def __init__(self, *args): # cls(*args) --> 走的是被装饰类的创建对象流程,然后把返回的对象 # 存放在装饰器类实例对象的一个静态属性中。 self.__instance = cls(*args) # 最终访问的是装饰器类返回的实例,这个实例的属性与被装饰类实例的属性是 # 一样的。实现方法就是:属性的传递。 def __getattr__(self, name): return getattr(self.__instance, name) return tmp_C @decorator class Person def __init__(self, name, sex): self.name = name self.sex = sex # 末尾自动加上代码:Person = decorator(Person) x = Person(‘Tim‘, ‘Male‘) # x = Person(‘Tim‘, ‘Male‘) ---> Person已经
# 相当于tmp_C了,调用的是tmp_C.__init__ print(x.name) # 调用的是 getattr(Person对象, name), 返回的是:‘Tim‘
3.1.2. 类方式实现
各种实现都存在缺点,推荐使用函数方式。类方式主要特点是考虑,__init__ 会被decorator()调用,对象调用,obj(),会调用decorator.__call__方法。
4. 装饰器嵌套
+-------------------------+-------------------------+ | @A | | | @B | | | @C | fc = C(my_func) | | def my_func(..): | fb = B(fc) | | ... | fa = A(fb) | +-------------------------+-------------------------+ | @A | | | @B | | | @C | cc = C(MyClass) | | class MyClass: | bc = B(cc) | | ... | ac = A(bc) | +-------------------------+-------------------------+
5. 装饰器参数
+----------------------------+----------------------------+ | @decorator(A,B) | def func(): | | def func(): | .... | | .... | f1 = decorator(A,B) | | | func = f1(func) | +----------------------------+----------------------------+ | func() | decorator(A,B)(func)() | +----------------------------+----------------------------+ def decorator(A,B): def f1(func): def f2(*args_for_func): ... return f2 return f1
6. 总结
装饰器的核心:通过语法结构,隐藏在被装饰函数之后,需要插入一段固定代码的方法。
- 不带参数的装饰器:被装饰对象同名对象 = 装饰器(被装饰对象),运行时顺序:执行装饰器内函数 -> 被装饰函数
- 带参数的装饰器:
- 被装饰对象同名对象 = ( 装饰器(装饰器参数) )(被装饰对象)
- == 等价于 ==
- 临时对象 = 装饰器(装饰器参数) # 会执行装饰器函数,返回中间函数
- 被装饰对象同名对象 = 临时对象( 被装饰对象 ) # 会执行装饰器内部的函数,并返回最底层一级封装函数
- 嵌套装饰器:
- 被装饰对象同名对象 = ( 最外层装饰器( 中间装饰器... ( 最内层装饰器 ( 被装饰对象 ) ) )
- == 等价于 ==
- 最内层装饰后临时对象 = 最内层装饰器 ( 被装饰对象 ) # 会执行装饰器函数,并返回封装函数
- 中间装饰后临时对象 = 中间装饰器 ( 最内层装饰后临时对象 ) # 会执行装饰器函数,并返回封装函数
- 被装饰对象同名对象 = 最外层装饰器 ( 中间装饰后临时对象 ) # 会执行装饰器函数,并返回封装函数
- 运行时顺序:最外侧 -> 中间层 -> 最内层 -> 被装饰函数
以上是关于[TimLinux] Python 装饰器的主要内容,如果未能解决你的问题,请参考以下文章