9

This works:

class MyClass(object):
    pass

someinstance = MyClass()
someinstance.myattribute = 42
print someinstance.myattribute
>>> 42

But this doesn't:

someinstance = object()
someinstance.myattribute = 42
>>> AttributeError: 'object' object has no attribute 'myattribute'

Why? I've got a feeling, that this is related to object being a built-in class, but I find this unsatisfactory, since I changed nothing in the declaration of MyClass.

Turion
  • 4,482
  • 4
  • 21
  • 38

4 Answers4

8

As for the rationale behind this, the words of the BDFL himself:

This is prohibited intentionally to prevent accidental fatal changes to built-in types (fatal to parts of the code that you never though of). Also, it is done to prevent the changes to affect different interpreters residing in the address space, since built-in types (unlike user-defined classes) are shared between all such interpreters.

Claudiu
  • 206,738
  • 150
  • 445
  • 651
8

Python stores attributes in a dict. You can add attributes to MyClass, see it has a __dict__:

>>> class MyClass(object):
>>>   pass
>>> dir(MyClass)
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']

The important difference is that object has no __dict__ attribute.

>>> dir(object)
['__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']

More detailed explanations:

Community
  • 1
  • 1
lecodesportif
  • 9,527
  • 8
  • 31
  • 53
1
>>> type(object)
type 'type'
>>> type(MyClass)
type 'classobj'

Here the important difference is MyClass is a user defined class object. Where you can modify your class.

object() however is a __builtin__ class object.

When you inherit from object which is your base class as well as __builtin__, you can modify only your new MyClass that you defined.

warvariuc
  • 50,202
  • 34
  • 156
  • 216
Vijay
  • 884
  • 7
  • 14
1

For user-defined classes, setting an attribute on an object is actually modifying an dictionary of attributes, so you can add a new entry at any time. (Object's __dict__)

Attributes on built-in types are implemented differently, not as generic dictionary but directly as the memory layout of the underlying implementation. Because the dictionary does not exist, and the class cannot be changed at runtime, you cannot add new attribute values to built-in objects.

Please see:

http://webcache.googleusercontent.com/search?q=cache:z4to2IGbKDUJ:www.velocityreviews.com/forums/t593269-cant-set-attributes-of-built-in-extension-type.html+setattr+built+in+class&cd=3&hl=en&ct=clnk&gl=us&client=firefox-a&source=www.google.com

http://mail.python.org/pipermail/python-dev/2008-February/077180.html

http://mail.python.org/pipermail/python-list/2010-April/1240731.html

elliot42
  • 3,446
  • 3
  • 23
  • 26