Why does this raise an error:
o = object() o.i = 1 But this does not:
class A(object): pass a = A() a.i = 1 ?
Because built-in types don't have dictionaries associated with them to hold added attributes:
>>> o = object() >>> dir(o) ['__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__'] See? No __dict__.
But adding a subclass gives the attribute somewhere to go:
>>> class A(object): .... pass .... >>> a = A() >>> dir(a) ['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__'] Saying that it's "because they're defined in C" isn't a "why". You could certainly define a type in C with an instance dictionary.
object is defined in C. You cannot add arbitrary attributes to instances of types defined in C unless you fill the appropriate slots in the type definition.