Let me first explain why this occurs:
class MyClass():
datastore = {}
def __init__(self):
self.datastore = {} # calls __setattr__
As you can see, your first variable definition in __init__
ends up calling __setattr__
def __setattr__(self, key, value):
self.datastore[key] = value
The instance does not yet have the datastore
attribute because it is still in the process of being defined. So this line self.datastore[key] = value
first trys to look up datastore
in the instance's __dict__
but can't find it! Then it looks up one level in the class tree, where it does find it, as a class attribute!
Remember this:
class MyClass():
datastore = {}
This is pretty confusing to begin with, since you have both an instance variable and a class variable with the same name, you should not have both.
So you can change your __init__
to this:
object.__setattr__(self, 'datastore', {})
Like @Dhara suggested, or you can use the more general approach which I would recommend:
super(MyClass, self).__setattr__('datastore', {})
Where the latter option only works for new-style classes (which are better in every way!) which you should be using!
Just add object
as a superclass
class MyClass(object): # In Py3k you don't need to since all classes are newstyle
One thing to note:
def __setattr__(self, key, value):
self.datastore[key] = value
Only works because you are setting the key of a dictionary and not an attribute of the instance. Be careful not to do things like
def __setattr__(self, key, value):
self.datastore = {} # for example
because that will result in infinite recursion, if you ever want to do something similar in __setattr__
use the same trick from before:
def __setattr__(self, key, value):
super(MyClass, self).__setattr__('datastore', {})
The final result should look like:
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