我知道在多个属性中使用setter
和getter
,当任何属性更改时,如何触发相同的功能?
例如,以下代码将设置器添加到属性a
。
class AAA(object):
def __init__(self):
...
@property
def a(self):
...
@a.setter
def a(self, value):
...
如果该类具有很多属性,例如a
,b
,...,z
,并且我想在任何属性更改时打印类似property xxx is modified
的内容
一个个地添加相似的getter和setter是愚蠢的。
我已经阅读了一些相关的问题和答案,但是找不到许多属性的解决方案。
答案 0 :(得分:4)
元编程,使用__setattr__
拦截修改:
class AAA(object):
def __setattr__(self, attr, value):
print("set %s to %s" % (attr, value))
super().__setattr__(attr, value)
aaa = AAA()
aaa.x = 17
# => set x to 17
print(aaa.x)
# => 17
您可以对__getattr__
进行类似的操作以读取权限。
答案 1 :(得分:1)
您可以使用descriptors。用外行的术语来说,描述符是可重用的属性。与__getattr__
和__setattr__
挂钩相比的优势在于,您可以更精细地控制由描述符管理的属性。
class MyDescriptor:
def __init__(self, default='default'):
self.default = default
def __set_name__(self, owner, name): # new in Python3.6
self.name = name
def __get__(self, instance, owner):
print('getting {} on {}'.format(self.name, instance))
# your getter logic here
# dummy implementation:
if instance is not None:
try:
return vars(instance)[self.name]
except KeyError:
return self.default
return self
def __set__(self, instance, value):
print('setting {} on {}'.format(self.name, instance))
# your getter logic here
# dummy implementation:
vars(instance)[self.name] = value
class MyClass:
a = MyDescriptor()
b = MyDescriptor()
_id = 1
# some logic for demo __repr__
def __init__(self):
self.c = 'non-descriptor-handled'
self.id = MyClass._id
MyClass._id += 1
def __repr__(self):
return 'MyClass #{}'.format(self.id)
演示:
>>> m1 = MyClass()
>>> m2 = MyClass()
>>> m1.c
'non-descriptor-handled'
>>> m1.a
getting a on MyClass #1
'default'
>>> m1.b
getting b on MyClass #1
'default'
>>> m1.b = 15
setting b on MyClass #1
>>> m1.b
getting b on MyClass #1
15
>>> m2.b
getting b on MyClass #2
'default'
答案 2 :(得分:0)
问了这个问题一年后,我发现了一种更简洁的方法来将getter和setter添加到多个相似的属性中。
只需执行一个更“抽象”的功能,该功能返回装饰的属性。并使用for循环将这些属性的每一个传递给此函数。然后添加所有这些属性的getter和setter。
def propABC(arg):
# arg: 'a', 'b', 'c'
@property
def prop(self):
_arg = '_' + arg
return getattr(self, _arg)
@prop.setter
def prop(self, val):
_arg = '_' + arg
setattr(self, _arg, val)
print(f"Set prop {_arg}")
return prop
for key in ['a', 'b', 'c']:
exec(f"{key} = propABC('{key}')")