1. 装饰器

  1. 一种语法格式,用于替换另外一个编码风格,一种语法糖,通过语法结构明确标识出这样一种语法。
  2. 自动在被装饰对象尾部执行代码(不使用装饰器语法时,需要明确写明的代码)
  3. 被装饰对象可以为函数、类,被装饰对象为函数(则定义装饰器为函数装饰器),被装饰对象为类(则定义装饰器为类装饰器)
  4. 装饰器自身可以是函数、类。

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. 总结

装饰器的核心:通过语法结构,隐藏在被装饰函数之后,需要插入一段固定代码的方法。
  1. 不带参数的装饰器:被装饰对象同名对象 = 装饰器(被装饰对象),运行时顺序:执行装饰器内函数 -> 被装饰函数
  2. 带参数的装饰器:
    • 被装饰对象同名对象 = ( 装饰器(装饰器参数) )(被装饰对象)
    • == 等价于 ==
    • 临时对象 = 装饰器(装饰器参数)  # 会执行装饰器函数,返回中间函数
    • 被装饰对象同名对象 = 临时对象( 被装饰对象 )  # 会执行装饰器内部的函数,并返回最底层一级封装函数
  3. 嵌套装饰器:
    • 被装饰对象同名对象 = ( 最外层装饰器( 中间装饰器... ( 最内层装饰器 ( 被装饰对象 ) ) )
    • == 等价于 ==
    • 最内层装饰后临时对象 = 最内层装饰器 ( 被装饰对象 )  # 会执行装饰器函数,并返回封装函数
    • 中间装饰后临时对象 = 中间装饰器 ( 最内层装饰后临时对象 )  # 会执行装饰器函数,并返回封装函数
    • 被装饰对象同名对象 = 最外层装饰器 ( 中间装饰后临时对象 )  # 会执行装饰器函数,并返回封装函数
    • 运行时顺序:最外侧 -> 中间层 -> 最内层 -> 被装饰函数

[TimLinux] Python 装饰器的更多相关文章

  1. 关于python装饰器

    关于python装饰器,不是系统的介绍,只是说一下某些问题 1 首先了解变量作用于非常重要 2 其次要了解闭包 def logger(func): def inner(*args, **kwargs) ...

  2. python装饰器通俗易懂的解释!

    1.python装饰器 刚刚接触python的装饰器,简直懵逼了,直接不懂什么意思啊有木有,自己都忘了走了多少遍Debug,查了多少遍资料,猜有点点开始明白了.总结了一下解释得比较好的,通俗易懂的来说 ...

  3. Python 装饰器学习

    Python装饰器学习(九步入门)   这是在Python学习小组上介绍的内容,现学现卖.多练习是好的学习方式. 第一步:最简单的函数,准备附加额外功能 1 2 3 4 5 6 7 8 # -*- c ...

  4. python 装饰器修改调整函数参数

    简单记录一下利用python装饰器来调整函数的方法.现在有个需求:参数line范围为1-16,要求把9-16的范围转化为1-8,即9对应1,10对应2,...,16对应8. 下面是例子: def fo ...

  5. python 装饰器学习(decorator)

    最近看到有个装饰器的例子,没看懂, #!/usr/bin/python class decorator(object): def __init__(self,f): print "initi ...

  6. Python装饰器详解

    python中的装饰器是一个用得非常多的东西,我们可以把一些特定的方法.通用的方法写成一个个装饰器,这就为调用这些方法提供一个非常大的便利,如此提高我们代码的可读性以及简洁性,以及可扩展性. 在学习p ...

  7. 关于python装饰器(Decorators)最底层理解的一句话

    一个decorator只是一个带有一个函数作为参数并返回一个替换函数的闭包. http://www.xxx.com/html/2016/pythonhexinbiancheng_0718/1044.h ...

  8. Python装饰器由浅入深

    装饰器的功能在很多语言中都有,名字也不尽相同,其实它体现的是一种设计模式,强调的是开放封闭原则,更多的用于后期功能升级而不是编写新的代码.装饰器不光能装饰函数,也能装饰其他的对象,比如类,但通常,我们 ...

  9. Python装饰器与面向切面编程

    今天来讨论一下装饰器.装饰器是一个很著名的设计模式,经常被用于有切面需求的场景,较为经典的有插入日志.性能测试.事务处理等.装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量函数中与函数 ...

随机推荐

  1. Linux基础知识回顾

    1.描述计算机的组成及其功能 计算机是由计算机软件系统和计算机硬件系统两大系统组成 计算机硬件组成 1946年数学家冯诺依曼提出,计算机硬件由运算器.控制器.存储器.输入设备和输出设备5大部件组成,如 ...

  2. java编程思想第四版第七章总结

    1. 实现类的复用通常有两种方式 组合:在新的类中产生现有类的对象 继承:按照现有类的类型来创造新类 2. 一个特殊的方法toString() 在非基本类型的对象中, 都有toString()方法 当 ...

  3. scipy.sparse的csc_matrix、csr_matrix与coo_matrix区别与应用(思维导图)

  4. Mac 下安装并配置 Tomcat

    1,下载 点击 官网 ,进入下载页面, 2,安装 解压出来,即安装完成. 移动解压后的文件,换个文件目录(方便集中管理),将它改个名字(毕竟名字太长了). 我将其改名为 tomcat9 ,移入资源库目 ...

  5. 搭建wordPress遇到无法连接数据库的问题

    在确认了数据库用户,密码,地址都没有错的情况下,仍然出现无法连接数据库的问题,以至无法安装wordpress 我的wordpress:4.8.1-zh_CN 解决办法: 1.更改php的版本(我的改为 ...

  6. PHP与Python进行数据交互

    最近,决定在一个项目用tp5进行APP接口开发,用Python做数据分析,然后这就面临一个问题:PHP和Python如何进行数据交互? 思路 我解决此问题的方法是利用了PHP的passthru函数来调 ...

  7. 利用tomcat搭建图片服务器

    今天来教大家如何使用 tomcat 来搭建一个图片的服务器 1.先将tomcat解压一份并改名 2.此时apache-tomcat-8.5.43-windows-x64-file为图片服务器 依次打开 ...

  8. MyISAM与InnoDB两者之间区别与选择

    一.MyISAM与InnoDB两者之间区别 1.MyISAM:默认表类型,它是基于传统的ISAM类型,ISAM是Indexed Sequential Access Method (有索引的顺序访问方法 ...

  9. 基于HTTP协议的WAF绕过

    一,畸形包绕过 1.先关闭burpsuite长度更新,为get请求,先使用bp的method转换为POST请求 2.get请求中空格使用%20代替,Connection改为keep-alive 二,分 ...

  10. 有效的减少代码中太多的if、else?-策略模式

    写这篇文章的目的和上一篇单例模式一样,策略模式也是一种常用的设计模式,太多的if-else不仅看着不太美观而且不好维护,对于自己来说也等于复习了一遍策略模式.先说一下策略 模式的定义: 策略模式封装了 ...