当装饰器机制为类时,类成员上的Python装饰器失败 [英] Python decorators on class members fail when decorator mechanism is a class

查看:79
本文介绍了当装饰器机制为类时,类成员上的Python装饰器失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在创建用于类方法的装饰器时,当装饰器机制是类而不是函数/闭包时,我会遇到麻烦。使用类形式时,我的装饰器不会被视为绑定方法。

When creating decorators for use on class methods, I'm having trouble when the decorator mechanism is a class rather than a function/closure. When the class form is used, my decorator doesn't get treated as a bound method.

通常,我更喜欢将函数形式用于装饰器,但在这种情况下,我必须使用现有的类来实现所需的东西。

Generally I prefer to use the function form for decorators but in this case I have to use an existing class to implement what I need.

这似乎与 python-decorator-makes-function-forget-它属于一个类,但是为什么它对于该函数形式却很好?

This seems as though it might be related to python-decorator-makes-function-forget-that-it-belongs-to-a-class but why does it work just fine for the function form?

这是我可以用来显示所有情况的最简单示例。对不起,代码量:

Here is the simplest example I could make to show all goings on. Sorry about the amount of code:

def decorator1(dec_param):
    def decorator(function):
        print 'decorator1 decoratoring:', function
        def wrapper(*args):
            print 'wrapper(%s) dec_param=%s' % (args, dec_param)
            function(*args)
        return wrapper
    return decorator

class WrapperClass(object):
    def __init__(self, function, dec_param):
        print 'WrapperClass.__init__ function=%s dec_param=%s' % (function, dec_param)
        self.function = function
        self.dec_param = dec_param

    def __call__(self, *args):
        print 'WrapperClass.__call__(%s, %s) dec_param=%s' % (self, args, self.dec_param)
        self.function(*args)

def decorator2(dec_param):
    def decorator(function):
        print 'decorator2 decoratoring:', function
        return WrapperClass(function, dec_param)
    return decorator

class Test(object):
    @decorator1(dec_param=123)
    def member1(self, value=1):
        print 'Test.member1(%s, %s)' % (self, value)

    @decorator2(dec_param=456)
    def member2(self, value=2):
        print 'Test.member2(%s, %s)' % (self, value)

@decorator1(dec_param=123)
def free1(value=1):
    print 'free1(%s)' % (value)

@decorator2(dec_param=456)
def free2(value=2):
    print 'free2(%s)' % (value)

test = Test()
print '\n====member1===='
test.member1(11)

print '\n====member2===='
test.member2(22)

print '\n====free1===='
free1(11)

print '\n====free2===='
free2(22)

输出:

decorator1 decoratoring: <function member1 at 0x3aba30>
decorator2 decoratoring: <function member2 at 0x3ab8b0>
WrapperClass.__init__ function=<function member2 at 0x3ab8b0> dec_param=456
decorator1 decoratoring: <function free1 at 0x3ab9f0>
decorator2 decoratoring: <function free2 at 0x3ab970>
WrapperClass.__init__ function=<function free2 at 0x3ab970> dec_param=456

====member1====
wrapper((<__main__.Test object at 0x3af5f0>, 11)) dec_param=123
Test.member1(<__main__.Test object at 0x3af5f0>, 11)

====member2====
WrapperClass.__call__(<__main__.WrapperClass object at 0x3af590>, (22,)) dec_param=456
Test.member2(22, 2)        <<<- Badness HERE!

====free1====
wrapper((11,)) dec_param=123
free1(11)

====free2====
WrapperClass.__call__(<__main__.WrapperClass object at 0x3af630>, (22,)) dec_param=456
free2(22)


推荐答案

您的 WrapperClass 必须是一个描述符(就像一个函数一样!),即提供适当的特殊方法 __ get __ __ set __ 此操作指南教了您所有有关此事的知识!-)

Your WrapperClass needs to be a descriptor (just like a function is!), i.e., supply appropriate special methods __get__ and __set__. This how-to guide teaches all you need to know about that!-)

这篇关于当装饰器机制为类时,类成员上的Python装饰器失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆