我有一个类在我的项目中执行一些有用的工作
class Test:
def __init__(self):
self.__value = None
def set_value(self, value):
print(f"set_value(): value={value}")
self.__value = value
def get_value(self):
print(f"get_value()")
return self.__value
value = property(get_value, set_value)
在常规函数中,它有一些 getters/setters,可以方便地分组为更简单的客户端代码的属性。例如
t.value = 123
现在,在应用程序的某些部分,我需要在每次访问 Test 对象、每次方法调用时执行一些额外的操作(在我的例子中是 print() 调用)。所以我这样做了:
class Wrapper:
def __init__(self, wrapped):
self.wrapped = wrapped
def __getattr__(self, attr):
print(f"Wrapper::__getattr__(): {attr}")
return getattr(self.wrapped, attr)
这与装饰器的做法非常相似,但这种方法有两个好处:
现在使用代码:
t = Test()
w = Wrapper(t)
w.set_value(123)
print(f"Value: {w.get_value()}")
w.value = 234
print(f"Value: {w.value}")
直接设置/获取呼叫按预期工作。不幸的是 w.value 语法不再起作用,并且默默地将值 234 分配给
value
名称,而不是调用 getter 和 setter。
如何解决此问题,以便 Wrapper 尊重 Test 类属性?
您可以定义一个
__setattr__
方法来管理分配。请注意,它必须单独处理 wrapped
属性,以避免 __init__
中的无限递归。
class Test:
def __init__(self):
self.__value = None
def set_value(self, value):
print(f"set_value(): value={value}")
self.__value = value
def get_value(self):
print(f"get_value()")
return self.__value
value = property(get_value, set_value)
class Wrapper:
def __init__(self, wrapped):
self.wrapped = wrapped
def __getattr__(self, attr):
print(f"Wrapper::__getattr__(): {attr}")
return getattr(self.wrapped, attr)
def __setattr__(self, attr, value):
if attr == 'wrapped':
super().__setattr__('wrapped', value)
else:
print(f"Wrapper::__setattr__(): {attr}")
setattr(self.wrapped, attr, value)
t = Test()
w = Wrapper(t)
w.set_value(123)
print(f"Value: {w.get_value()}")
print()
w.value = 234
print(f"Value: {w.value}")
输出:
Wrapper::__getattr__(): set_value
set_value(): value=123
Wrapper::__getattr__(): get_value
get_value()
Value: 123
Wrapper::__setattr__(): value
set_value(): value=234
Wrapper::__getattr__(): value
get_value()
Value: 234