python系列--修饰器(decorator)

1. 修饰器 

1.1 函数作为修饰器

python的修饰器(decorator)是一项重要的语法,能够发挥出重要作用。理解修饰器的关键是认识到修饰器其实就是给函数包裹了一层函数。以下面这段代码为例子: 

@myDecorator
def aFunction():
    print "inside aFunction"

当编译aFunction函数时,编译器会先经过myDecorator函数,进而返回一个函数,然后把这个函数赋值给aFunction。所以,在运行aFunction()时,就相当于运行了myDecorator里面的东西。如果我们直接打印aFunction函数对象,会发现修饰前后是不同的。 

为了保证修饰前后是相同的,我们可以使用一个修饰器@wraps。该修饰器可以保留函数的元信息,方便后期debug。[1]  

from functools import wraps 

def tags(tag_name):
    def tags_decorator(func):
        @wraps(func) 
        def func_wrapper(name):
            return "<{0}>{1}</{0}>".format(tag_name, func(name))
        return func_wrapper
    return tags_decorator


@tags("p")
def get_text(name):
    return "Hello "+name


print(get_text("John"))
print(get_text)
print(get_text.__name__)


# the result is   (without @wraps)
<p>Hello John</p>
<function tags.<locals>.tags_decorator.<locals>.func_wrapper at 0x7fa8b755e9d8>
func_wrapper


# the result is   (with @wraps)
<p>Hello John</p>
<function get_text at 0x7f2c2d4059d8>
get_text

可以看出,加入了@wraps以后,get_text函数的元信息被保留了。

1.2 类作为修饰器   

利用类来作为修饰器其实更好理解修饰器机理。能够更加看清楚修饰器构建以及作用的时间。[2]     

class NewDecorator(object):
    
    def __init__(self, f):
        print("inside myDecorator.__init__()")
        # f() # Prove that function definition has completed
        self.f = f 

    def __call__(self, *args, **kwargs):
        print("inside myDecorator.__call__()")
        result = self.f(*args, **kwargs)
        return result 


@NewDecorator 
def add_num(a, b):
    return a+b 


print(add_num)
print("after the decorator") 
result = add_num(1,3)
print(result)


# the result is  
inside NewDecorator.__init__()
<__main__.NewDecorator object at 0x7f7ee79190f0>
after the decorator
inside NewDecorator.__call__()
4

修饰器其实就是给函数加上了一个函数,这一部分在构造函数里面完成,同时也会返回一个函数给原来函数,这里就是__call__函数。


2. @property修饰器 

property修饰器是python类中比较常见的一个修饰器,其主要的功能就是为了方便管理类中的成员变量。

class Celsius:
    def __init__(self, temperature = 0):
        self._temperature = temperature

    def to_fahrenheit(self):
        return (self.temperature * 1.8) + 32

    @property
    def temperature(self):
        print("Getting value")
        return self._temperature

    @temperature.setter
    def temperature(self, value):
        if value < -273:
            raise ValueError("Temperature below -273 is not possible")
        print("Setting value")
        self._temperature = value

主要是为了方便赋值,并且可以在赋值或是取值时做类型检测和有效性判断 。[3]

参考: 
[1] https://www.thecodeship.com/patterns/guide-to-python-function-decorators/  
[2] https://www.artima.com/weblogs/viewpost.jsp?thread=240808    
[3] https://www.programiz.com/python-programming/property

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值