如何从"流体"中检索参数。装饰功能

时间:2016-02-20 17:10:02

标签: python python-decorators

假设我有这个装饰者:

def decorator(f):
  def f_wrap(*args):
    for item in args:
      print(args)
    return f(*args)
  return f_wrap

用作"永久"具有@语法的装饰器args检索包装函数的参数。例如,当与下面的类一起使用时,我会收到MyObject的实例。

Class MyObject(object):
  def __init__(self):
    pass

  @decorator
  def function(self):
    return

如何使用"流体"来实现相同的结果?装饰。还是装饰者没有永久地绑定到它正在装饰的功能?例如:

def decorator(f):
    def f_wrap(*args):
        if (not args):
            print("Nothing in args")
        return f(*args)
    return f_wrap

class MyClass(object):
    def __init__(self):
        pass

    def function(self):
        return

if __name__ == "__main__":
    myobj = MyClass()
    myobj.function = decorator(myobj.function)
    myobj.function()

在这种情况下,args元组总是返回空(我总是得到" args&#34中没有任何东西;),即使我预期它会返回实例变量myobj

修改

如果@AChampion的帖子不清楚,解决办法就是简单地将流体装饰的方法称为"未绑定的"方法。如,

from types import MethodType
def decorator(f):
    def f_wrap(*args):
        # I replaced this with an iteration through
        #   args. It's a bit more demonstrative.
        for item in args:
            print(item)
        return f(*args)
    return f_wrap

class MyClass(object):
    def __init__(self):
        pass

    def function(self):
        return

if __name__ == "__main__":
    myobj = MyClass()
    myobj.function = MethodType(decorator(MyClass.function), myobj)
    myobj.function()

2 个答案:

答案 0 :(得分:2)

您没有正确使用allall会在all中检查的内容中​​是否符合所有条件,返回一个bool。在你的情况下,你并没有真正做任何事情。您将始终使用all评估为True。

我相信你所寻找的只是这个:

if not args:

现在,最终检查的是你正在执行的方法是否有* args。对于你所拥有的函数的情况,你没有传递任何参数,因此,通过if not args检查,你实际上会得到:

"Nothing in args"

但是,如果您为方法添加一个参数:

def function(self, x):
    return

然后致电:myobj.function(1)

得到" args"

回答您关于未获取实例的最后一个问题。如果您使用这种调用装饰器的方法打印f

myobj.function = decorator(myobj.function)
myobj.function()

您将获得绑定方法:

<bound method MyClass.function of <__main__.MyClass object at 0x102002390>>

现在,设置你的装饰师:

@decorator
def function(self):
    return

您将看到附加到类对象的函数:

<function MyClass.function at 0x102001620>

因此表明他们并没有做你期望的完全相同的事情。希望这有助于澄清一点。

答案 1 :(得分:2)

区别的原因是你要包装不同的东西,一个未绑定的方法与一个绑定的方法:

class MyObject(object):
    @decorator
    def function(self):
         pass

相当于:

import types
class MyClass(object):
    def function(self):
        pass

m = MyClass(object)
m.function = types.MethodType(decorator(MyClass.function), m)

m.function = decorator(m.function)

第一个是未绑定的方法,第二个是绑定方法。

相关问题