通过装饰器将实例变量动态添加到Python中的类

时间:2010-07-16 14:18:02

标签: python

我想通过装饰器来设置一个类,添加一些由类的作者指定的实例变量。

我从以下代码开始,但这只是添加变量,我想要实例变量(那些通常在__ init __中声明'的变量)

什么是pythonic方法,同时允许类作者控制他们放在__ init __中的内容?

def add_list_attributes(klass):
    for attribute in klass.list_attributes:
        setattr(klass, attribute, [])

    return klass

@add_list_attributes
class Person(object):

    list_attributes = [
        'phone_numbers'
    ]

    def __init__(self):
        pass

p1 = Person()
p1.phone_numbers.append('01234')

print p1.phone_numbers

3 个答案:

答案 0 :(得分:2)

您必须将__init__()包装在一个单独的函数中,该函数将调用原始方法,然后将其自己的属性添加到第一个参数。

答案 1 :(得分:2)

您可以通过包装__init__方法进行出价,然后调用原始__init__

来执行此操作
def add_list_attributes(klass):
    old_init = klass.__init__
    def new_init(self, *args, **kwargs):
        for attribute in klass.list_attributes:
            setattr(self, attribute, [])
        old_init(self, *args, **kwargs)
    klass.__init__ = new_init
    return klass

@add_list_attributes
class Person(object):

    list_attributes = [
        'phone_numbers'
    ]

    def __init__(self):
        pass

p1 = Person()
p1.phone_numbers.append('01234')
p2 = Person()
p2.phone_numbers.append('56789')

print p1.phone_numbers
print p2.phone_numbers

答案 2 :(得分:2)

您可以创建自定义__new__方法:

def add_list_attributes(klass):
    def new(cls, *args, **kwargs):
        result = super(cls, cls).__new__(cls)
        for attribute in klass.list_attributes:
            setattr(result, attribute, [])
        return result
    klass.__new__ = staticmethod(new)
    return klass

@add_list_attributes
class Person(object):
    list_attributes = [
        'phone_numbers'
    ]
    def __init__(self):
        pass

p1 = Person()
p2 = Person()
p1.phone_numbers.append('01234')

print p1.phone_numbers, p2.phone_numbers