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. java annotation(如何创建新的注解)小结

    "注解"有三种 1:无实际参数,只有声明 2:只存在单一参数,有些像方法调用 3:有多个参数 标准的"注解"就先不总结了. 想总结一下<如何创建自己的注解 ...

  2. 简单理解gqrx是什么

    gqrx:Gqrx是一个基于gnuradio和Qt架构,开发的一个开源的SDR接收机的应用.下图是他的一个运行界面: gnu radio GNU Radio是一个自由软件开发工具包,提供实现软件无线电 ...

  3. 【笔记】gitlab+openldap使用memberof筛选登录用户

    这几天在搞kerberos+nfs4 没搞成 之前搞了个openldap实现了分散控制集中管理(不是DCS...) gitlab和nexus也支持ldap 虽然都不咋好用 但是在搞gitlab的时候发 ...

  4. String类对象的常用操作及方法

    在Java中,String类包含有50多个方法来实现字符串的各种操作,以下介绍一些我们需要经常使用的方法.1.字符串的连接public String concat(String str) 该方法的参数 ...

  5. 压缩打包,tar

    压缩打包命令 创建压缩包 tar -zcvf /home/xxxx.tar.gz /xahot 解压 tar -zxvf xxx.tar.gz gzip   xxxx  自动变为 xxx.gz

  6. vim 转换大小写

    只转化某个单词 guw .gue gUw.gUe 这样,光标后面的单词便会进行大小写转换 想转换5个单词的命令如下: gu5w.gu5e gU5w.gU5e 转换几行的大小写 4.转换几行的大小写 将 ...

  7. 吴恩达老师机器学习课程chapter11——大规模机器学习

    吴恩达老师机器学习课程chapter11--大规模机器学习 本文是非计算机专业新手的自学笔记,高手勿喷. 本文仅作速查备忘之用,对应吴恩达(AndrewNg)老师的机器学期课程第十七章. 这是这次整理 ...

  8. linux 修改PATH 环境变量

    [root@localhost ~]# echo $PATH [root@localhost ~]# vim /etc/profile 最后一行加上 export PATH=****/bin:$PAT ...

  9. C语言 数据编码方式

    一.整形数据类型 1.无符号数的编码 无符号数指的是整个机器字长的全部位数均表示数值位. 我们用函数      来进行运算.(B2U是Binary to Unsigned的缩写,长度为w),x代表为0 ...

  10. 记下HTML中图片的路径

    1 <!doctype html> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 < ...