我正在使用来自here的代码片段以及我自己在ironpython中的修改,这些修改效果非常好:
from System.ComponentModel import INotifyPropertyChanged, PropertyChangedEventArgs
from Library.pyevent import make_event
class Notify_property(property):
''' defines a notifiable property
'''
def __init__(self, getter):
def newgetter(slf):
#return None when the property does not exist yet
try:
return getter(slf)
except AttributeError:
return None
super(Notify_property, self).__init__(newgetter)
def setter(self, setter):
def newsetter(slf, newvalue):
# do not change value if the new value is the same
# trigger PropertyChanged event when value changes
oldvalue = self.fget(slf)
if oldvalue != newvalue:
setter(slf, newvalue)
slf.OnPropertyChanged(setter.__name__)
return property(
fget=self.fget,
fset=newsetter,
fdel=self.fdel,
doc=self.__doc__)
class NotifyPropertyChangedBase(INotifyPropertyChanged):
''' The base of the MVVM view model
Here the bound properties are added in addition with its
handlers.
'''
# handlers which get fired on any change register here
PropertyChanged = None
''' handlers that only get fired on their property change register here
they are organized in a dictionary with the property name as key and
a list of handlers as value
'''
_property_handlers = {}
def __init__(self):
''' we create an event for the property changed event
'''
self.PropertyChanged, self._propertyChangedCaller = make_event()
def add_PropertyChanged(self, value):
''' helper function to wrap the += behaviour
'''
self.PropertyChanged += value
def remove_PropertyChanged(self, value):
''' helper function to wrap the -= behaviour
'''
self.PropertyChanged -= value
def OnPropertyChanged(self, propertyName):
''' gets fired on an property changed event
'''
if self.PropertyChanged is not None:
self._propertyChangedCaller(self, PropertyChangedEventArgs(propertyName))
try:
for property_handler in self._property_handlers[propertyName]:
property_handler(propertyName,PropertyChangedEventArgs(propertyName))
except KeyError:
pass
def add_notifiable_property(self, notifiable_property):
self.add_handled_property((notifiable_property,None))
def add_notifiable_property_list(self, *symbols):
for symbol in symbols:
self.add_notifiable_property(symbol)
def add_handled_property_list(self, *symbols):
for symbol in symbols:
self.add_handled_property(symbol)
def add_handled_property(self, notifiable_property):
symbol = notifiable_property[0]
if notifiable_property[1] is not None:
self._property_handlers[notifiable_property[0]] = notifiable_property[1]
dnp = """
import sys
sys.path.append(__file__)
@Notify_property
def {0}(self):
return self._{0}
@{0}.setter
def {0}(self, value):
self._{0} = value
""".format(symbol)
d = globals()
exec dnp.strip() in d
setattr(self.__class__, symbol, d[symbol])
现在我必须承认我并不完全理解所有代码。主要是使用Notify_property类对我来说是一个谜。为了更好地理解我试图删除属性的代码。从我的MainViewModel调用哪个子类上面的类我可以通过:
定义一个属性add_notifiable_property('TestProperty')
或
add_handled_property((TestProperty,[handler1,handler2])
我也可以删除处理程序(尚未实现)但是如何再次删除属性?
del self.TestProperty
除了
undeletable attribute
和
delattr(self,'TestProperty')
除了
delattr takes exactly 2 arguments 2 given
很奇怪。
我还尝试在我的基类中添加一个函数:
def remove_notifiable_property(self,propertyname):
''' removes a notifiable property
'''
self._property_handlers.pop(propertyname,None)
exec "del self.{0}".format(propertyname)
但是关于不可删除的属性会收到相同的错误。
如何再次删除设置属性?
编辑:我发现我错过了删除功能。将此代码添加到上面的dnp字符串现在会导致新的错误:@{0}.deleter
def {0}(self):
del self._{0}
出现新错误:
Derived calss has no attribute _TestProperty
TestProperty是我添加的名称。还是卡住了。
EDIT2: 我将其跟踪到以下内容:
class C(object):
def __init__(self):
pass#self._x = None
@property
def x(self):
"""I'm the 'x' property."""
return self._x
@x.setter
def x(self, value):
self._x = value
@x.deleter
def x(self):
del self._x
c = C()
print dir(c)
c.x = 'A'
print c.x
print dir(c)
del c.x
print dir (c)
显示相同的行为。错误no _来自缺少初始化属性。添加:
exec """self._{0} = None""".format(symbol)
到add_handled_property的最后一行修复它。
但是属性本身仍然用dir显示,也不再在类中了。这是python中的错误吗?
答案 0 :(得分:1)
你应该能够做到
delattr(self.__class__, 'TestProperty')
因为属性在类__dict__
中。见最后一行:
setattr(self.__class__, symbol, d[symbol])
使用类A中的类A,实例a和属性p在Python中如何使用属性的示例:
>>> class A(object):
class Property(object):
def __get__(*args):
print 'get:', args
def __set__(*args):
print 'set:', args
def __delete__(*args):
print 'del:', args
p = Property()
>>> A.p
get: (<__main__.Property object at 0x7f3e16da4690>, None, <class '__main__.A'>)
>>> a = A()
>>> a.p
get: (<__main__.Property object at 0x7f3e16da4690>, <__main__.A object at 0x7f3e16da4910>, <class '__main__.A'>)
>>> a.p = 3
set: (<__main__.Property object at 0x7f3e16da4690>, <__main__.A object at 0x7f3e16da4910>, 3)
>>> del a.p
del: (<__main__.Property object at 0x7f3e16da4690>, <__main__.A object at 0x7f3e16da4910>)
你可以在课堂上替换它们
>>> A.p = 2
>>> a.p
2
或从班级
中删除它们>>> A.p = A.Property()
>>> del A.p