简体   繁体   English

Python:使用相同的装饰器装饰__call__和普通函数?

[英]Python: decorate __call__ and ordinary function with the same decorator?

Is it possible in Python 2.6-2.7 to use the same decorator for the following task: 在Python 2.6-2.7中是否可以使用相同的装饰器执行以下任务:

class ComplextCallableObject(object):
    @wrap_me
    def __call__(self, a1, a2):
        pass

@wrap_me
def simple_function(a1, a2):
    pass

Both ComplextCallableObject.__call__ and simple_function has the same args, but __call__ also has self for the first arg. ComplextCallableObject.__call__simple_function都具有相同的args,但__call__也具有第一个arg的self In the wrap_me decorator I need an access for the function being wrapped args. wrap_me装饰器中,我需要访问被包装的函数args。

Unfortunately, at the time of definition (the class block in this case), the code cannot tell how a function will be used except by naming convention. 不幸的是,在定义时(本例中为类块),除了命名约定之外,代码无法告诉函数如何使用。 Modifying your example a bit: 稍微修改你的例子:

class ComplextCallableObject(object):
    @wrap_me
    def __call__(self, a1, a2):
        pass #...

@wrap_me
def simple_function(tgt, a1, a2):
    pass

ComplextCallableObject.anInstanceMethod = simple_function
ComplextCallableObject.anClassMethod = classmethod(simple_function)
ComplextCallableObject.aStaticMethod = staticmethod(simple_function)

In this case, simple_function is implementing a function taking a target and two parameters, an instance method taking two parameters, a class method taking two parameters, and a static method taking a target and two parameters. 在这种情况下, simple_function正在实现一个采用目标和两个参数的函数,一个采用两个参数的实例方法,一个采用两个参数的类方法,一个采用目标和两个参数的静态方法。 But these uses are not bound until after the function is defined. 但是这些用法在定义函数之后才会被绑定。 Both staticmethod and classmethod return a different object type, so you can tell those apart, if need be. staticmethodclassmethod返回不同的对象类型,因此如果需要,您可以区分它们。

If you did want to use convention, you could inspect the function's first argument name to see if it is self : 如果您确实想使用约定,则可以检查函数的第一个参数名称以查看它是否为self

def wrap_me(fn):
    names = fn.func_code.co_varnames
    if names and names[0]=='self':
        print 'looks like an instance method'
    else: print 'looks like a function'
    return fn
def wrap_me(*args):
    a1, a2 = args if len(args) == 2 else args[1:]
    ...

Of course, you will need to modify the returned function to take the self argument if wrap_me was called on a class method as well. 当然,如果在类方法上调用了wrap_me ,则需要修改返回的函数以获取self参数。

By the way, assuming you're not actually using self inside the function which you're decorating, it should really be a static method. 顺便说一句,假设你实际上没有在你正在装饰的函数中使用self ,它应该是一个静态的方法。

This may be pretty dumb, but might as well work for the simplest case: 这可能相当愚蠢,但也可能适用于最简单的情况:

In [1]: def wrap_me(func):
   ...:     def wrapped(*args):
   ...:         print 'arg1 is', args[-2]
   ...:         print 'arg2 is', args[-1]
   ...:         func(*args)
   ...:     return wrapped
   ...:
In [2]: class ComplexCallableObject(object):
   ...:     @wrap_me
   ...:     def __call__(self, a1, a2):
   ...:         print 'class object called'
   ...:
In [3]: @wrap_me
   ...: def simple_function(a1, a2):
   ...:     print 'function called'
   ...:
In [4]: simple_function('A', 'B')
arg1 is A
arg2 is B
function called
In [5]: o = ComplexCallableObject()
In [6]: o('A', 'B')
arg1 is A
arg2 is B
class object called

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM