python和它的装饰器

即使你没听过装饰器,你也一定知道@staticmethod

作为函数的装饰器,你可以这样写

def mydecorator(function):

    def wrapped(*args, **kwargs):

        # 在调用原始函数之前, 做点什么
result = function(*args, **kwargs)
# 在函数调用之后, 做点什么
# 并返回结果
return result
# 返回warpper作为装饰函数
return wrapped

作为一个例子,我写了个非常随意的

def print_hello(function):

    def hello(*args, **kwargs):

        print('hello start')
result = function(*args, **kwargs)
print('hello end')
return 'hello %s' % result
return hello @print_hello
def print_world(): print('world print')
return 'world result' if __name__ == '__main__': print(print_world())

它的结果是

hello start
world print
hello end
hello world result

作为类的装饰器,你可以这样写

class DecoratorAsClass(object):

    def __init__(self, function):

        self.funciton = function

    def __call__(self, *args, **kwargs):

        # 在调用原始函数之前, 做点什么
result = self.funciton(*args, **kwargs)
# 在调用函数之后, 做点什么
# 并返回结果
return result

作为一个例子,我依旧写了一个很随意的

class PrintWrappedClass(object):

    def __init__(self, function):

        self.function = function

    def __call__(self, *args, **kwargs):

        print('wrapped start')
result = self.function(*args, **kwargs)
print('wrapped end')
return result @PrintWrappedClass
class PrintWorld (object): def print_world(self): print('world print')
return 'world result' def print_kitty(self): print('kitty print')
return 'kitty result' if __name__ == '__main__':
print(PrintWorld().print_world())
print('___')
print(PrintWorld().print_kitty())

它的结果是

wrapped start
wrapped end
world print
world result
___
wrapped start
wrapped end
kitty print
kitty result

当然,装饰器也可以传参

def repeat(number=3):

    def actual_decorator(function):

        def wrapper(*args, **kwargs):

            result = None
for _ in range(number):
result = function(*args, **kwargs)
return result
return wrapper
return actual_decorator @repeat(2)
def print_kitty(): print('kitty print')
return 'kitty result' if __name__ == '__main__': print(print_kitty())

它的结果是

kitty print
kitty print
kitty result

然后我想了想,为什么不像函数装饰器的模板那么写呢?

于是,我就随意地写了个错误的例子

def error_repeat(function, number=3):

    def wrapper(*args, **kwargs):

        result = None
for _ in range(number):
result = function(*args, **kwargs)
return result
return wrapper @error_repeat
def print_world(): print('world print')
return 'world result'

它的结果是

world print
world print
world print
world result

很完美,但是当我想传参数进去的时候,犯难了

呃,就姑且将这个错误的示例当做个笑话看看吧

保存内省的装饰器

from functools import wraps

def preserving_decorator(function):

    @wraps(function)
def wrapped(*args, **kwargs): # 包装函数内部文档
return function(*args, **kwargs)
return wrapped

说实话,我没看懂这段

所以摘录下书中的原话

使用装饰器的常见错误是在使用装饰器时不保存函数元数据(主要是文档字符串和原始函数名)。

前面所有示例都存在这个问题。

装饰器组合创建了一个新函数,并返回一个新对象,但却完全没有考虑原始函数的标识。这将使得调试这样装饰过的函数更加困难,也会破坏可能用到的大多数自动生成文档的工具,因为无法访问原始的文档字符串和函数签名。

摘自 《Python高级编程》

【摘】python和它的装饰器的更多相关文章

  1. Python中利用函数装饰器实现备忘功能

    Python中利用函数装饰器实现备忘功能 这篇文章主要介绍了Python中利用函数装饰器实现备忘功能,同时还降到了利用装饰器来检查函数的递归.确保参数传递的正确,需要的朋友可以参考下   " ...

  2. python函数与方法装饰器

    之前用python简单写了一下斐波那契数列的递归实现(如下),发现运行速度很慢. def fib_direct(n): assert n > 0, 'invalid n' if n < 3 ...

  3. guxh的python笔记三:装饰器

    1,函数作用域 这种情况可以顺利执行: total = 0 def run(): print(total) 这种情况会报错: total = 0 def run(): print(total) tot ...

  4. python设计模式之内置装饰器使用(四)

    前言 python内部有许多内建装饰器,它们都有特别的功能,下面对其归纳一下. 系列文章 python设计模式之单例模式(一) python设计模式之常用创建模式总结(二) python设计模式之装饰 ...

  5. python 3.x 的装饰器笔记

    今天学到了python的装饰器,感觉这个东西还是稍微有些复杂,所以记录下来,方便以后的查找.虽然标题是python 3.x的装饰器,但是我也没有怎么用过python 2.x,感觉上应该是和python ...

  6. python 中多个装饰器的执行顺序

    python 中多个装饰器的执行顺序: def wrapper1(f1): print('in wrapper1') def inner1(*args,**kwargs): print('in inn ...

  7. Python函数编程——闭包和装饰器

    Python函数编程--闭包和装饰器 一.闭包 关于闭包,即函数定义和函数表达式位于另一个函数的函数体内(嵌套函数).而且,这些内部函数可以访问它们所在的外部函数中声明的所有局部变量.参数.当其中一个 ...

  8. python基础-内置装饰器classmethod和staticmethod

    面向对象编程之classmethod和staticmethod classmethod 和 staticmethod都是python内置的装饰器 classmethod 的作用:给在类内部定义的方法装 ...

  9. Python 入门之 Python三大器 之 装饰器

    Python 入门之 Python三大器 之 装饰器 1.开放封闭原则: (1)代码扩展进行开放 ​ 任何一个程序,不可能在设计之初就已经想好了所有的功能并且未来不做任何更新和修改.所以我们必须允许代 ...

  10. python中面向对象之装饰器

    python面向对象内置装饰器property,staticmethod,classmethod的使用 @property 装饰器作用及使用 作用:面向对象中的方法伪装成属性 使用如下: class ...

随机推荐

  1. 关于 dangerouslySetInnerHTML

    之前不太了解react,第一次看dangerouslySetInnerHTML,以为可以用来防止xss注入. 后面看待又补充了一个DOMPurify,才知道这个东西只有一个提醒的作用,并不能防止xss ...

  2. SqlServer的主键和外键

    SqlServer在创建表时要有 完整性约束(主键)和参照性约束(外键) 1.在建表时创建主键 第一种方法: 第二种方法: 联合主键,即2个主键,sid和cid 2.如果表已经存在,需要创建主键 外键

  3. centos5.7 x64,安装java17,提示 glibc 版本低

    安装java17,网站下载tar版本. 解压后,配置/etc/profile 的java_home,和path, 运行java -version  和 javac -version  提升缺少GLIB ...

  4. 嵌入式开发er的C语言能力自测(面试)题---top 16

    准备面试刷到的,链接里是原文和答案: (a-c-test-the-0x10-best-questions-for-would-be-embedded-programmers) 这里我先只给出问题,可以 ...

  5. Java 向上转型

    向上转型: 对象的向上转型,其实就是多态写法: 父类名称 对象名 = new 子类名称(); 注意:向上转型一定是安全的,从小范围转向大范围.(从小范围的猫,向上转化为更大范围的动物)

  6. mysql添加到环境变量

    今天换新系统,以前的一些常用软件重新安装了一下,安装到mysql我还是按照以前的习惯选择了低版本的5.7系列,突然想要装一把,像python一样可以直接访问解释器,能不能直接在cmd中输入mysql就 ...

  7. 本地JAR包如何上传私有仓库

    需求背景 有些第三方的jar包需要手动上传到maven私有仓库,以便通过maven来管理依赖. 为简化手动上传的jar包的操作步骤,所以整了个脚本,在使用时只需修改相应变量即可. 脚本示例 #!/bi ...

  8. 代码行数统计(指定目录下所有文件的Line)

    遍历文件夹计算文件行数(Windows) 主要使用的是 FindFirstFile. FindNextFile函数寻找子目录下的文件,使用 WIN32_FIND_DATA(文件属性) 结构体 #def ...

  9. 使用laydate时间输入控件

    下载 layDate 后,将文件夹 laydate 整个放置在您的项目任意目录,使用时只需引入 laydate.js 即可. 详细的使用方法见:https://www.layui.com/laydat ...

  10. Mongodb设置账号密码登录

    Mongodb设置.首先设置Data目类和Log目录,然后新建mongodb.conf,设置内容大体如下 port = 27017 #数据目录 dbpath = /usr/softs/data/db ...