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. SAP SD VA01 销售订单中的自动价格更新

    场景 :当用户使用假定物料" A"创建销售订单时,确定了价格,但随后用户意识到需要更改物料,因此他们更改了订单中的物料. 现在,它显示价格已经重新确定,但是在项目条件页面中时,他们 ...

  2. 网络-7 IPv6(下)

    Ipv6实验 一.华为 思科与华为在接口启用ipv6 思科会自动产生local地址 华为不会自动产生local地址 以太网接口有mac地址,所以肯定是有eui64 serial接口是没有mac地址,他 ...

  3. EMQX Cloud Serverless 正式上线:三秒部署、按量计费的 MQTT Serverless 云服务

    近日,全球领先的开源物联网数据基础设施软件供应商 EMQ 正式发布了 MQTT Serverless 云服务 -- EMQX Cloud Serverless 的 Beta 版本,开创性地采用弹性多租 ...

  4. mysql索引相关知识

    一.什么情况下会使索引失效? 二.sql优化您们是怎么做的? 1.首先开启数据库慢查询日志,定位到查询效率比较低的sql , 找出对应的sql语句并进行分析 1.表设计是否规范,是否符合三范式的标准( ...

  5. potoshop制作一寸照片

    potoshop制作一寸照片 经常因为各种原因需要提供1寸照片,第一反应应还是跑照相馆专业.但是疫情封闭在家怎么高,刚好把偶尔使用一次的potoshop用起来,解决照片制作问题,一来能省几毛钱买茶叶蛋 ...

  6. 全链路压测SOP

    压测模型构建:人工 线上(大促)流量数据 (数据脱敏) 日常流量数据 业务方新的特性产生的变更数据 友商做过的事情 压测模型构建:自动 流程包括:录制-清洗-回放 (目前能做好的公司非常少) 压测标准 ...

  7. Windows初始化.net core环境

    1.项目使用.ner core版本(例:.net core.3.1) 1.1安装运行环境 https://dotnet.microsoft.com/en-us/download 1.2安装.net 运 ...

  8. ubuntu iptables 做为路由转发

    实现功能,本地服务器的号段的192.168.8.0/24,而做为路由器的机器有2个ip,192.168.8.x和另一个ip,而另一个ip可以访问 192.168.2.0/24号段, 为了让其它192. ...

  9. StatefulWidget 有状态组件 、 页面上绑定数据、改变页面数据

    一.Flutter 中自定义有状态组件 在 Flutter 中自定义组件其实就是一个类,这个类需要继承 StatelessWidget/StatefulWidget. StatelessWidget ...

  10. Web前端单词大全

    style 修饰width 宽度height 高度title 想说明的text-align 水平对齐方式center 居中 left 居左 right 居右line-height 垂直对齐方式/行高 ...