3

I can create a python object like this

class Test:
   pass

t1 = Test()
t1.var = "value"
t1.num = 100

and can see the dictionary of the object using

print(t1.__dict__)
# prints
{'var': 'value', 'num': 100}

Does this mean that python objects are internally stored as dictionaries?

Daksh Gupta
  • 7,554
  • 2
  • 25
  • 36

1 Answers1

1

Simple Explanation

No. But internally, all Python objects (except those defined with __slots__, or Python builtins) use dictionaries for dynamic attribute access.

As you can see in the following example, using __slots__ makes the type not store an internal dictionary, which prevents dynamically setting methods, fields, or other information to the type. However, the size of the type is reduced as a result.

In [7]: class A:
   ...:     __slots__ = ('fields')
   ...:     def __init__(self):
   ...:         self.fields = 1
   ...:       

In [9]: dir(A)
Out[9]: 
['__class__',
'__delattr__',
'__dir__',
'__doc__',
'__eq__',
'__format__',
'__ge__',
'__getattribute__',
'__gt__',
'__hash__',
'__init__',
'__init_subclass__',
'__le__',
'__lt__',
'__module__',
'__ne__',
'__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__setattr__',
'__sizeof__',
'__slots__',
'__str__',
'__subclasshook__',
'fields']

If you take a look at the CPython source code, you will also see most builtin types are not stored as dictionaries, either:

#ifndef Py_LIMITED_API
typedef struct {
    PyObject_HEAD
    double ob_fval;
} PyFloatObject;
#endif

Rationale

To understand why all classes that allow dynamically setting variables, methods, and other information use dicts internally to store this information, we need to consider what dictionaries are extremely good at: O(1) information access with O(1) insertions and deletions. Since the interpreter does not know which attributes the class may have, if that attribute is a variable, method, etc. until runtime, this requires using some sort of container bound to the class at runtime. In other languages, like C++, this is achieved using an array of function pointers (typically, although not guaranteed), or a virtual table, allowing you to dynamically change a predefined set of methods to the class. However, since the method name is already harded-coded, this does not allow dynamically adding or removing methods to the class. Any approach except a hashmap or binary search tree may be unable to efficiently allow dynamic typing.

tldr

Mostly, yes. Optimally, no. Use __slots__ to minimize the size of your classes.

Alex Huszagh
  • 13,272
  • 3
  • 39
  • 67