3

From https://docs.python.org/3.3/library/functions.html#object

object does not have a __dict__, so you can’t assign arbitrary attributes to an instance of the object class.

Why "object does not have a __dict__"? It works for me

>>> object.__dict__
mappingproxy({'__repr__': <slot wrapper '__repr__' of 'object' objects>, '__hash__': <slot wrapper '__hash__' of 'object' objects>, '__subclasshook__': <method '__subclasshook__' of 'object' objects>, '__ne__': <slot wrapper '__ne__' of 'object' objects>, '__format__': <method '__format__' of 'object' objects>, '__new__': <built-in method __new__ of type object at 0xa3dc20>, '__doc__': 'The most base type', '__class__': <attribute '__class__' of 'object' objects>, '__dir__': <method '__dir__' of 'object' objects>, '__delattr__': <slot wrapper '__delattr__' of 'object' objects>, '__getattribute__': <slot wrapper '__getattribute__' of 'object' objects>, '__le__': <slot wrapper '__le__' of 'object' objects>, '__init__': <slot wrapper '__init__' of 'object' objects>, '__gt__': <slot wrapper '__gt__' of 'object' objects>, '__ge__': <slot wrapper '__ge__' of 'object' objects>, '__eq__': <slot wrapper '__eq__' of 'object' objects>, '__reduce__': <method '__reduce__' of 'object' objects>, '__lt__': <slot wrapper '__lt__' of 'object' objects>, '__str__': <slot wrapper '__str__' of 'object' objects>, '__reduce_ex__': <method '__reduce_ex__' of 'object' objects>, '__sizeof__': <method '__sizeof__' of 'object' objects>, '__setattr__': <slot wrapper '__setattr__' of 'object' objects>})

Why "you can’t assign arbitrary attributes to an instance of the object class"?

Tim
  • 1
  • 141
  • 372
  • 590

1 Answers1

14

You are confusing the __dict__ on the type with the attribute on instances. object() instances do not have a __dict__ attribute:

 >>> object().__dict__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'object' object has no attribute '__dict__'

Note that the __dict__ attribute of custom Python class instances is a descriptor; the instance itself doesn't have the attribute, it is the class that provides it (so type(instance).__dict__['__dict__'].__get__(instance) is returned). object.__dict__ may exist, but object.__dict__['__dict__'] does not.

object() doesn't support instance attributes because it is the base for all custom Python classes, which must support not having a __dict__ attribute when defining slots instead.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • Thanks. If I am correct, an instance of a class has `__dict__` attribute. So why doesn't an instance of `object` have `__dict__` attribute? – Tim Jul 03 '17 at 07:48
  • @Tim: because if it did, you couldn't have custom class instances *without* a `__dict__` attribute, such as for those classes that [have slots instead](https://docs.python.org/3/reference/datamodel.html#slots). – Martijn Pieters Jul 03 '17 at 07:49
  • Thanks. Why "you can’t assign arbitrary attributes to an instance of the object class"? – Tim Jul 03 '17 at 07:51
  • 1
    @Tim: You need a `__dict__` mapping to support arbitrary attributes. That's how arbitrary attributes *work*. – Martijn Pieters Jul 03 '17 at 07:51
  • Does "an instance of object doesn't have `__dict__` attribute" imply that `object` class has `__slot__` attribute? – Tim Jul 03 '17 at 07:52
  • @Tim: no, it does not. `__slots__` defines fixed attributes *in addition* to what the base provided. – Martijn Pieters Jul 03 '17 at 07:53
  • Thanks. "`object()` doesn't support instance attributes because it is the base for all custom Python classes". `object` is the base for all classes, while an instance of `object` is not. So why does an instance of `object` not have `__dict__` attribute? – Tim Jul 03 '17 at 18:34
  • @Tim: *Because* `object` is the base class for all custom classes, it informs instances. The class of the instance provides the `__dict__` descriptor; if `object` provided that then you can't have an instance without a `__dict__`. Ergo, `object()` instances can't have a `__dict__`. – Martijn Pieters Jul 03 '17 at 19:32
  • "The class of the instance provides the `__dict__` descriptor; if `object` provided that then you can't have an instance without a `__dict__`". (1) Do you mean if a class has class attribute `__dict__` , then every instance of the class has instance attribute `__dict__`? (2) here, the class `object` has class attribute `__dict__` , but your reply says that the return of `object()`, i.e. any instance of the class `object`, has no instance attribute `__dict__`. So isn't that contrary to (1)? – Tim Jul 03 '17 at 20:43
  • 1
    @Tim: I linked to the [descriptor howto](https://docs.python.org/3/howto/descriptor.html) for a reason. Please read it. Attributes on instances can be satisfied in 2 different ways: keys in the `__dict__`, and attributes on the class hierarchy. Attributes on the class hierarchy can be *descriptors*, which then get *bound* to the instance. `__dict__` is implemented as such a descriptor, so **the class supplies it**. So yes, because the class (or a parent of the class) has a `__dict__` attribute that happens to be a descriptor, that attribute works on all instances. Just like methods. – Martijn Pieters Jul 03 '17 at 20:52
  • 2
    @Tim: Note that the same applies to `type`; it can supply descriptors for classes (including `object`). `object.__dict__` is not actually an attribute directly on `object`, it is a descriptor that `type` provides; `object.__dict__` is really `type.__dict__['__dict__'].__get__(object)`. There is no `object.__dict__['__dict__']` however. – Martijn Pieters Jul 03 '17 at 20:55