Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python interaction between __setattr__ and self.__dict__

Tags:

python

If I make a class instance like this

class MyClass(object):
    pass
x = MyClass()

I can then set attributes on x as follows:

x.myAttr = 1 or x.__setattr__('myAttr', 1)

However, if I make a dict

d = {}

I cannot set attributes on it. For example, if I do this

d.__setattr__('myAttr', 1)

I get the error " 'dict' object has no attribute 'myAttr' " The same thing happens if I try

d.myAttr = 1

I have noticed that in the case of x.myAttr = 1 what actually happens is that

x.__dict__

gets updated with a new key, so it must be that

d.__setattr__

doesn't work because d doesn't have

d.__dict__

simply because d is a dict. I would appreciate it very much if someone could thoroughly explain what's going on here.

Do all python objects have .__dict__?

Why does my attempt at calling d.__setattr__ result in an error saying that the attribute doesn't exist?

Is there a specific heirarchy of built-in types that I should know about? A simple reference would be much appreciated.

python 2.6.4

Windows XP Pro x64 SP2

like image 861
Martinis Group Avatar asked Jun 05 '12 17:06

Martinis Group


People also ask

What does __ Setattr __ do in python?

Python setattr() method is used to assign the object attribute its value.

What is the usage of Setattr () function?

Python setattr() function is used to assign a new value to the attribute of an object/instance. Setattr in python sets a new specified value argument to the specified attribute name of a class/function's defined object.


2 Answers

A dict instance doesn't have a __dict__ attribute, so you can't assign attributes on it. Most of Python's built-in classes (which are written in C and define attributes differently) don't. If you subclass dict, the subclass will have a __dict__ attribute and you can then add attributes to instances of the subclass.

like image 199
kindall Avatar answered Sep 28 '22 02:09

kindall


copy-paste from docs.python.org:

A special attribute of every module is __dict__. This is the dictionary containing the module’s symbol table. Modifying this dictionary will actually change the module’s symbol table, but direct assignment to the __dict__ attribute is not possible (you can write m.__ dict__['a'] = 1, which defines m.a to be 1, but you can’t write m.__dict__ = {}). Modifying __dict__ directly is not recommended.

http://docs.python.org/library/stdtypes.html

The method

Both lines do the same:

x.__setattr__('a', b)
x.a = b

Like __ add__ is:

x.__add__(b)
x + b

However, you can redefine a dict.__ setattr__ function to whatever you want

edit for 3rd comment:

class x(object):
    def __init__(self):
        pass
    def __setattr__(self, a, b):
        print "nope, i will not set the attribute %s = %s" % (a,b)

c = x()
c.a = 4
print c.__dict__

will print "nope, i will not set the attribute a = 4 and c.__dict__ won't have the attribute 'a'

like image 36
AlbertFerras Avatar answered Sep 28 '22 04:09

AlbertFerras