Python:将所有实例属性更改为属性

时间:2016-12-09 07:19:17

标签: python properties attributes instance

假设我们有10个属性:

class test(object):
  def __init__(self,a,b,c,d,e,f,g,h,i,j):
    self._a = a
    #the same with the rest of variables

是否可以使它们成为所有属性?:

@property
def a(self):
  return self.a
@a.setter
def a(self,a_new):
  #invoke other functions doing other stuff when attribute values change
  self._a = a_new

如果在更改任何实例属性时需要运行相同的函数,是否必须为每个属性键入以上代码?是否可以编写代码然后将其用作自定义装饰器或类似的东西?

如果自定义装饰器是可行的,那么我可以覆盖某些属性的setter函数吗?

1 个答案:

答案 0 :(得分:1)

如果确实希望所有实例属性都是属性,则可以实现__setattr____getattribute__方法。这是一个简短的演示:

class Test(object):
    attr_names = {'a', 'b', 'c', 'd'}

    def __init__(self, a, b, c, d):
        self.a = a
        self.b = b
        self.c = c
        self.d = d

    def __repr__(self):
        return 'Test({}, {}, {}, {})'.format(self.a, self.b, self.c, self.d)

    def __setattr__(self, name, value):
        if name in Test.attr_names:
            print('Setting {} to {}'.format(name, value))
            super().__setattr__(name, value)
        else:
            raise AttributeError("Can't set unknown attribute: " + name)

    def __getattribute__(self, name):
        if name in Test.attr_names:
            print('Getting {}'.format(name))
            return super().__getattribute__(name)
        else:
            raise AttributeError("Can't get unknown attribute: " + name)

t = Test(1, 2, 3, 4)
print(t)
t.b = 7
print(t)

try:
    t.e = 42
except AttributeError as err:
    print(err)

<强>输出

Setting a to 1
Setting b to 2
Setting c to 3
Setting d to 4
Getting a
Getting b
Getting c
Getting d
Test(1, 2, 3, 4)
Setting b to 7
Getting a
Getting b
Getting c
Getting d
Test(1, 7, 3, 4)
Can't set unknown attribute: e

此代码适用于Python 3.在Python 2中,您需要将适当的参数传递给super

super(Test, self)

例如

super(Test, self).__setattr__(name, value)

有关这些方法的详情,请参阅data model docs