我先解释一下为什么会出现这种情况:
class MyClass():
datastore = {}
def __init__(self):
self.datastore = {} # calls __setattr__
如您所见,您的第一个变量定义__init__
最终调用__setattr__
def __setattr__(self, key, value):
self.datastore[key] = value
该实例还没有该datastore
属性,因为它仍在定义过程中。所以这条线self.datastore[key] = value
首先尝试datastore
在实例__dict__
中查找但找不到它!然后它在类树中查找一个级别,它确实找到了它,作为一个类属性!
记住这一点:
class MyClass():
datastore = {}
一开始这很令人困惑,因为您有一个实例变量和一个同名的类变量,您不应该同时拥有这两个变量。
所以你可以改变你__init__
的:
object.__setattr__(self, 'datastore', {})
就像@Dhara 建议的那样,或者您可以使用我推荐的更通用的方法:
super(MyClass, self).__setattr__('datastore', {})
后一个选项仅适用于您应该使用的新型类(各方面都更好!)!只需添加object
为超类
class MyClass(object): # In Py3k you don't need to since all classes are newstyle
需要注意的一件事:
def __setattr__(self, key, value):
self.datastore[key] = value
仅在您设置字典的键而不是实例的属性时才有效。小心不要做类似的事情
def __setattr__(self, key, value):
self.datastore = {} # for example
因为这将导致无限递归,如果您想__setattr__
使用以前的相同技巧做类似的事情:
def __setattr__(self, key, value):
super(MyClass, self).__setattr__('datastore', {})
最终结果应如下所示:
class MyClass(object):
def __init__(self):
super(MyClass, self).__setattr__('datastore', {})
def __getattr__(self, key):
return self.datastore[key]
def __setattr__(self, key, value):
self.datastore[key] = value
a = MyClass()
b = MyClass()
a.hello = "err"
print a.hello
print b.hello