2012-03-12 106 views
3

是否有可能在Python 2.6-2.7使用相同的装饰以下任务:Python:使用相同的装饰器来装饰__call__和普通函数?

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

@wrap_me 
def simple_function(a1, a2): 
    pass 

两个ComplextCallableObject.__call__simple_function具有相同的ARGS,但__call__也有self的第一个参数。在wrap_me装饰器中,我需要访问包装参数的函数。

+0

'wrap_me'应该完成什么?如果两个函数采用不同的参数,它们是如何执行'wrap_me'-able任务的呢? – 2012-03-12 16:41:53

回答

2

不幸的是,在定义的时候(这种情况下的类块),除了命名约定之外,代码无法知道如何使用函数。修改你的例子有点:

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) 

在这种情况下,simple_function正在实施一项功能采取了目标和两个参数,一个实例方法接受两个参数,一个类的方法接受两个参数,一个静态方法,一个目标和两个参数。但是这些用途在定义函数之后才会被绑定。 staticmethodclassmethod都会返回不同的对象类型,所以如果需要的话,您可以区分这些对象。

如果你确实想使用约定,你可以检查该函数的第一个参数名称,看它是否是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 
0
def wrap_me(*args): 
    a1, a2 = args if len(args) == 2 else args[1:] 
    ... 

当然,你将需要修改返回的函数采取self说法,如果wrap_me拜访了一个类的方法为好。

顺便说一下,假设你实际上并没有在装饰的函数中使用self,它应该是一个静态方法。

+0

我在'__call__'中使用'self'(在'__init__'中初始化繁重的东西并在'__call__'中使用它),当我在'__call__'中不使用'self'时,我将这些对象转换为简单函数 – dmzkrsk 2012-03-12 13:52:02

+0

因此, “相同的”装饰器正在做两件不同的事情,这取决于它是在方法还是函数上调用?为什么不制作两个装饰器? – katrielalex 2012-03-12 18:12:06

0

这可能是非常愚蠢的,但还不如在简单的情况下工作:

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 
+0

糟糕,我忽略了katrielalex的答案,它基本上是一样的。如果没有人介意,我会让它挂在这里作为插图。 – 2012-03-13 08:58:18