python装饰器和描述器的使用总结

装饰器

毫无疑问在python中用得非常多

def deco(func):
    def _deco():
        print 'before invoked'
        func()
        print 'after invoked'
    return _deco

@deco
def f():
    print 'f is invoked'

在f上加deco装饰器相当于f = deco(f), 和functools.partial有些类似

如果被装饰的函数f带参数且有返回值

def deco(func):
    def _deco(*args, **kwargs):
        print 'before invoked'
        ret = func(*args, **kwargs)
        print 'after invoded'
        return ret
    return _deco

@deco
def f(a):
    print 'f is invoked'
    return a + 1

如果装饰器带有参数,需要多包一层,把参数调用包进去

def deco(*args):
    def _deco(func):
        def __deco(*args, **kwargs):
            print 'decorator args is', args
            print 'before invoked'
            ret = func(*args, **kwargs)
            print 'after invoded'
            return ret
        return __deco
    return _deco
   
@deco('test')
def f(a):
    print 'f is invoked'
    return a + 1

只有最里面一层的__deco才会每次都调用,其它外层函数只在包装时调用一次,当然,你可以在其中声明变量,然后拿到__deco里使用。如果需要保留函数名,则在__deco上加@functools.wraps装饰器

使用  作装饰器,注意是此时相当于装饰函数,被装饰的函数会作为实例化参数,得到一个类实例,以python wiki上一个做登录检查的代码为例

class LoginCheck:
    def __init__(self, f):
        self._f = f

    def __call__(self, *args):
        Status = check_function()
        if Status is 1:
            return self._f(*args)
        else:
            return alt_function()


def check_function():
    return test


def alt_function():
    return 'Sorry - this is the forced behaviour'


@LoginCheck
def display_members_page():
    print 'This is the members page'

描述器

描述器在监视特定属性的时候很有用,其只在新式类中起作用。所有的描述器协议如下:

descr.__get__(self, obj, type=None) --> value
descr.__set__(self, obj, value) --> None
descr.__delete__(self, obj) --> None

如果一个对象同时定义了 __get__() 和 __set__(),它叫做资料描述器(data descriptor)。仅定义了 __get__() 的描述器叫非资料描述器
描述器在属性访问时被自动调用。举例来说, obj.x 会在 obj 的字典中找x ,如果x定义了 __get__方法,那么 x.__get__(obj)会依据下面的优先规则被调用

调用优先级:
资料描述器 -> 实例字典 -> 非资料描述器

常用的描述器就是property了,一般都只实现了__get__的接口
先给出一个classmethod的实现和一个用于测试描述器优先级的类

class classproperty(object):
    def __init__(self, func):
        self.func = func

    def __get__(self, instance, owner):
        return self.func(owner)


class MyClass(object):

    @classproperty
    def name(cls):
        return cls.__name__

    @property
    def x(self):
        return self._data

    @x.setter
    def x(self, value):
        self._data = value

    @x.deleter
    def x(self):
        del self._data

    def __init__(self, val):
        self._data = val
        self.x = 3
        self.name = 'test'

接下来调用

s = MyClass(99)
print s.x
print s.name
print s.__dict__

很明显x是资料描述器,而name不是,所以结果是

3
5
{'_data': 3, 'name': 'test'}

如果给classproperty加上__set__,那么就会调用被装饰的name,而不是实例化时实例字典中的name

一个property的python 实现

原文代码如下

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
装饰器Python中一种强大的功能,允许在不修改原始函数的情况下,向函数添加额外的功能。装饰器使用@符号将其应用于函数。 一个装饰器函数通常具有以下形式: ```python def decorator(func): def wrapper(*args, **kwargs): # 添加额外的功能 return func(*args, **kwargs) return wrapper ``` 其中,`decorator`是装饰器函数本身,`wrapper`是内部函数,用于包装原始函数,并添加额外的功能。 装饰器可以应用于函数,类甚至是类的方法。通过在被装饰的函数或方法前使用装饰器函数,可以将装饰器应用于该函数或方法。 例如,引用中的代码展示了一个简单的装饰器模板,引用中的代码展示了一个使用装饰器实现函数计时的例子。在这个例子中,`timec`是装饰器函数,`wrapper`是内部函数用于计算函数执行的时间。被`timec`装饰的函数`con_add`和`join_add`会在执行前后输出运行时间。 引用中的代码展示了一个包含关键字的装饰器的例子。在这个例子中,`decorator`是装饰器函数,`wrapper`是内部函数用于在执行被装饰的函数前后输出时间。被`decorator`装饰的函数`f`接受两个位置参数和任意个关键字参数,并在执行前后输出相应的信息。 总之,装饰器Python中一种强大的功能,可以用于给函数或方法添加额外的功能,而不需要修改原始函数的代码。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Python装饰器使用](https://blog.csdn.net/belong_to_you/article/details/111003741)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [Python装饰器使用](https://blog.csdn.net/qq_43830639/article/details/95247941)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值