在Python中通过装饰器动态添加实例变量到类中
我想通过装饰器来给一个类添加一些实例变量,这些变量是由类的作者指定的。
我开始写了以下代码,但这段代码只添加了类变量,而我想要的是实例变量(通常是在__ init __中“声明”的变量)。
有什么更符合Python风格的方法可以做到这一点,同时又能让类的作者控制他们在__ 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 个回答
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
你需要把 __init__()
放在一个单独的函数里,这个函数会先调用原来的方法,然后再给第一个参数添加你自己的属性。
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