我使用以下类来定义事件:
class Event(object):
def __init__(self):
self.handlers = set()
def handle(self, handler):
self.handlers.add(handler)
return self
def unhandle(self, handler):
try:
self.handlers.remove(handler)
except:
raise ValueError("Handler is not handling this event, so cannot unhandle it.")
return self
def fire(self, *args, **kwargs):
for handler in self.handlers:
print(handler)
handler(*args, **kwargs)
def getHandlerCount(self):
return len(self.handlers)
__iadd__ = handle
__isub__ = unhandle
__call__ = fire
__len__ = getHandlerCount
我有一些像这样定义的模型类:
class SomeModel(object):
def __init__(self):
self._foo = 0
self.fooChanged = Event()
@property
def foo(self):
return self._foo
@foo.setter
def foo(self, value):
self._foo = value
self.fooChanged(value)
现在,假设我想这样更改foo
:
model = SomeModel()
other_model = SomeModel()
model.fooChanged += other_model.foo
model.foo = 1
model.foo = 1
之后,我会得到以下错误:
typeerror:'int'对象不是可呼叫
现在,假设我使用此代码来定义模型:
class SomeModel(object):
def __init__(self):
self._foo = 0
self.fooChanged = Event()
def get_foo(self):
return self._foo
def set_foo(self, value):
self._foo = value
self.fooChanged(value)
foo = property(get_foo, set_foo)
和此代码更改foo
的值:
model = SomeModel()
other_model = SomeModel()
model.fooChanged += other_model.set_foo
model.foo = 1
第二版效果很好,但是,对我来说似乎没有任何意义。我必须定义get_foo
方法,我想避免使用该方法(因为属性可用)。这里还有其他解决方法,因此可以运行的第一个版本的代码?
注意:错误将取决于self._foo
类型。如果是None
,它将返回错误,说明NoneType
是不可呼应的,如果是字符串,则错误将声明str
对象无法调用。
经过大量挖掘,我发现这个答案非常有用,它朝着正确的方向推动了我。
使用这些知识,我能够通过使用:
来解决此问题model.fooChanged += lambda value: type(other_model).foo.__set__(other_model, value)
或
model.fooChanged += lambda value: type(other_model).foo.fset(other_model, value)
后来的线对我来说看起来更加蓬松,因为没有呼叫双输入函数。
在您编写model.fooChanged += other_model.foo
时,我想您实际想要的是其Setter方法,但是由于other_model.foo
是属性对象,您必须从其类other_model.__class__.foo.fset
获得,并写为:
model.fooChanged += lambda value: other_model.__class__.foo.fset(other_model, value)
otoh,我认为您的第二版对我来说是Pythonic,as
显式比隐式更好。