在Python中分配(或重新重载)赋值运算符的麻烦

时间:2013-04-24 22:17:20

标签: python

我在分配赋值运算符时遇到了问题。

我已成功重载__setattr__。但是在初始化对象之后,我希望__setattr__做其他事情,所以我尝试将其指定为另一个函数__setattr2__

代码:

class C(object):

    def __init__(self):
        self.x = 0
        self.__setattr__ = self.__setattr2__

    def __setattr__(self, name, value):
        print "first, setting", name
        object.__setattr__(self, name, value)

    def __setattr2__(self, name, value):
        print "second, setting", name
        object.__setattr__(self, name, value)

c = C()
c.x = 1

我得到了什么:

first, setting x
first, setting __setattr__
first, setting x

我想要/期望的是什么:

first, setting x
first, setting __setattr__
second, setting x

2 个答案:

答案 0 :(得分:8)

From the docs

  

新式类的特殊方法查找

     

对于新式类,特殊方法的隐式调用是   只保证在对象的类型上定义时才能正常工作,而不是   在对象的实例字典中。这种行为就是原因所在   以下代码引发异常(与等效示例不同)   与旧式课程):

>>> class C(object):
...     pass
...
>>> c = C()
>>> c.__len__ = lambda: 5
>>> len(c)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: object of type 'C' has no len()

答案 1 :(得分:3)

为什么不使用标志来表示__init__仍在进行中?

class C(object):
    def __init__(self):
        # Use the superclass's __setattr__ because we've overridden our own.
        super(C, self).__setattr__('initialising', True)
        self.x = 0
        # the very last thing we do in __init__ is indicate that it's finished
        super(C, self).__setattr__('initialising', False)

    def __setattr__(self, name, value):
        if self.initialising:
            print "during __init__, setting", name
            # I happen to like super() rather than explicitly naming the superclass
            super(C, self).__setattr__(name, value)
        else:
            print "after __init__, setting", name
            super(C, self).__setattr__(name, value)