当对象的内容更改时,我试图触发一个函数。我试图通过装饰python中的 setattr 方法来执行此操作,因为使用=运算符时会调用此方法。
我尝试使用@decorator装饰 setattr 函数,并且此方法有效,但是我想尝试在运行时装饰它,以便我可以按对象的每个实例装饰它。到目前为止,我已经尝试了下面的代码。
class TestObject:
pass
def on_object_change(func):
def wrapper(*args, **kwargs):
print("value changed %s - %s" % (args, kwargs))
func(*args, **kwargs)
return wrapper
obj = TestObject()
wrapper = on_object_change(obj.__setattr__)
obj.__setattr__ = wrapper
obj.one = 1
obj.__setattr__("two", 2)
setattr(obj, "three", 3)
我希望输出为:
值已更改(“ one”,1)-{}
值已更改(“ two”,2)-{}
值已更改(“三”,3)-{}
但是实际输出是:
值已更改(“ two”,2)-{}
obj的内容已更改为1、2和3。但是没有调用包装函数。我只是想知道这是否是预期的行为。如果还有另一种装饰 setattr 功能的方法。
答案 0 :(得分:0)
更改代码以装饰类的方法,而不是对象的方法
class TestObject:
pass
def on_object_change(func):
def wrapper(*args, **kwargs):
print("value changed %s - %s" % (args[1:], kwargs))
func(*args, **kwargs)
return wrapper
wrapper = on_object_change(TestObject.__setattr__)
TestObject.__setattr__ = wrapper
现在,以下设置操作将导致以下提到的输出
obj = TestObject()
obj.one = 1
obj.__setattr__("two", 2)
setattr(obj, "three", 3)
输出
value changed ('one', 1) - {}
value changed ('two', 2) - {}
value changed ('three', 3) - {}
答案 1 :(得分:0)
如果要使用装饰器,为什么不使用decorator syntax?
def on_object_change(func):
def wrapper(*args, **kwargs):
print("value changed %s - %s" % (args, kwargs))
func(*args, **kwargs)
return wrapper
class TestObject:
@on_object_change
def __setattr__(self, *args, **kwargs):
super().__setattr__(*args, **kwargs)
obj = TestObject()
obj.one = 1
obj.__setattr__('two', 2)
setattr(obj, 'three', 3)
打印:
value changed (<__main__.TestObject object at 0x7f38da0f3b70>, 'one', 1) - {}
value changed (<__main__.TestObject object at 0x7f38da0f3b70>, 'two', 2) - {}
value changed (<__main__.TestObject object at 0x7f38da0f3b70>, 'three', 3) - {}
答案 2 :(得分:0)
我发现了一些问题
def on_object_change(func):
def wrapper(item, value):
print("value changed %s - %s" % (item, value))
func(item, value)
return wrapper
class TestObject:
def setattr(key, value):
super().__setattr__(key, value)
def __setattr__(self, key, value):
self.setattr(key, value)
obj = TestObject()
obj2 = TestObject()
obj.setattr = on_object_change(obj.setattr)
obj.one = 1
obj2.two = 2
由于 setattr 方法已绑定到该类,因此无法针对每个实例执行此操作。通过在这两个函数之间添加的桥梁,可以为每个TestObject实例添加一个包装器。
output obj.one = 1 -> value changed one - 1
output obj2.two = 2 ->
这正是我所需要的。