【问题标题】:self in python decoratorspython装饰器中的自我
【发布时间】:2011-12-04 14:10:06
【问题描述】:

我想要一个装饰器,它将装饰函数添加到列表中,如下所示:

class My_Class(object):

    def __init__(self):
        self.list=[]

    @decorator
    def my_function(self)
       print 'Hi'

我希望将 my_function 添加到 self.list,但我无法编写这个装饰器。如果我尝试在 My_Class 中编写它,那么我将不得不使用@self.decorator,并且 self 不存在,因为我们在任何函数之外。如果我尝试将它写出 My_Class,那么我将无法从 my_function 中检索 self。

我知道存在非常相似的问题,但它们过于复杂,我只是在学习 python 和装饰器。

【问题讨论】:

  • 顺便说一句,使用list 作为变量名不是很好(因为这会遮蔽内置list 类)。
  • 你想要一个被修饰的函数列表(每个函数出现一次),还是一个函数何时被调用的列表(每个函数可能出现多次)?
  • @ovgolovin 这个list 名字是对的,我上面写的是伪代码。 @interjay 我希望列表是特定于实例的,并且每个修饰函数一次。
  • @CGGJE:如果列表包含每个修饰函数一次,那么它肯定对于所有实例都是相同的。那么,为什么您希望它是特定于实例的呢?
  • 如果你想让每个函数在列表中出现一次,你可以使用set而不是list。但是set 不允许您跟踪订单。

标签: python decorator self


【解决方案1】:

您无法从装饰器访问self,因为装饰器在定义函数时运行,而那时还没有My_Class 的实例。

最好将函数列表作为类属性而不是实例属性。然后你可以把这个列表作为参数传递给装饰器:

def addToList(funcList):
    '''Decorator that adds the function to a given list'''
    def actual_decorator(f):
         funcList.append(f)
         return f
    return actual_decorator

class MyClass(object):
    funcList = []

    @addToList(funcList)
    def some_function(self, name):
        print 'Hello,', name

现在您可以访问MyClass.funcList 以获取修饰函数列表。

【讨论】:

  • 这是否意味着funcList 在类的实例之间共享?因为据我了解,这个想法是分别跟踪每个实例调用了哪些函数。
  • @ovgolovin:我读到这个问题是想要一份使用装饰器定义的函数的列表(每个函数只出现一次)。既然您提到了您的解释,我发现它也很有意义。我不确定是哪一个。
  • @CGGJE 如果您需要为每个实例设置单独的行为列表,请不要忘记在def __init__ 中创建funcList 的副本,否则您的所有实例将共享相同的funcList.
【解决方案2】:

为绑定函数(实例方法)编写装饰器并没有什么特别之处。例如,这个简单的例子可以正常工作:

def decorator(fn):
    print "I'm decorating!"
    return fn


class MyClass(object):
    def __init__(self):
        self.list = []

    @decorator
    def my_function(self):
        print "Hi"

如果你想在你的装饰器中使用self,你会像对待任何使用函数参数的装饰器一样对待你的装饰器:

def decorator(fn):
    def _decorator(self):
        print "I'm decorating, and here's my list: %s!" % self.list
        return fn(self)
    return _decorator

【讨论】:

  • MyClass 是否可以访问decorator? (decorator 超出类范围)。
  • 我不确定我是否理解“有权访问”,但是您可以使用此装饰器装饰您的类中的函数,只要在定义类之前定义此装饰器(通过导入,或将定义放在文件中,在类定义之前)。
  • 对了,为什么不能用self.fn()代替fn(self)呢?如果我进行此更改,我有一个例外。
  • 好吧,首先,你没有在类的实例上名为fn 的方法(至少在这个例子中)。在这种情况下, fn 只是一个恰好是函数的变量。为什么要进行此更改?
  • 改变只是为了更好地理解所有与类相关的东西会发生什么。但我不完全明白:当我使用self.fn(...) 时,Python 不应该调用fn(self,...) 吗?
【解决方案3】:

您的list 属性应该是一个类属性(并且应该重命名,因为list 是一个内置类型)。然后你可以这样做:

my_methods = []

def my_method(method):
    my_methods.append(method)
    return method


class MyClass(object):

    my_methods = my_methods

    @my_method
    def my_function(self):
       print 'Hi'

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-01-25
    • 2011-07-25
    • 1970-01-01
    • 2018-03-02
    • 1970-01-01
    • 2019-04-25
    • 1970-01-01
    相关资源
    最近更新 更多