删除python中的属性

时间:2013-05-15 14:06:44

标签: python mvvm ironpython

我正在使用来自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中的错误吗?

1 个答案:

答案 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