Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

__dict__ Attribute of Ultimate Base Class, object in Python

Following piece of code lists the attributes of a class named 'A' in a sorted order:-

>>> class A():
        def __init__(self, i):
            self.at = i

>>> sorted(vars(A))
['__dict__', '__doc__', '__init__', '__module__', '__weakref__']

Now, printing the value of key, '__dict__' results this:-

>>> vars(A)['__dict__']                 #Value of '__dict__'
<attribute '__dict__' of 'A' objects>

As per docs, vars([object])

Return the __dict__ attribute for a module, class, instance, or any other object with a __dict__ attribute.


What I am not understanding is that is the '__dict__' attribute in the list the same attribute used by vars() to return the attributes of A or is it a different attribute which has some another objective like implementing A's objects' namespace as suggested (according to me) by the value which '__dict__' holds.


Edit:-

The first part of the question is very much related to this other question (also, mentioned by @eliotness) but it's the second part (described below) for which I can't find any answers or related question and hence, changing title of the question.


Let's consider another code that produces list of attributes of ultimate base class in Python, object:-

>>> sorted(vars(object))
['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', ...., '__str__', '__subclasshook__']
>>> hasattr(object, '__dict__')
True
>>> sorted(getattr(object, '__dict__')) == sorted(vars(object))
True

Another quotation from docs about object.__dict__

A dictionary or other mapping object used to store an object’s (writable) attributes.


This time, '__dict__' doesn't show up in the list of object. So, is it that the __dict__ attribute is a read-only attribute in case of object or any other reason?

Also, is it possible to get a list of read-only attributes in Python in any way?


like image 513
Perspicacious Avatar asked Jul 03 '20 20:07

Perspicacious


People also ask

What is the__dict__attribute of an object in Python?

This returns the __dict__ attribute of obj, which contains all the attributes of the object which can be writable. Here, obj can be any module / class / instance of a class, etc. There are a couple of cases here, depending on the argument type and the number of arguments too.

How to get the class attributes of an object in Python?

The dir () function is used to list the attributes available for the objects. The ‘ dir ’ takes into consideration the instances, it’s class and inherited classes. __ dict __ only contains the local attributes of the object. To get the class attributes __ dict __ can be used on class Fruit.

What is ‘__Dict__’ in Python?

What is ‘ __dict__ ’ in Python? Python uses a special built-in attribute __dict__ to store object’s mutable attributes. Basically ‘__dict__’ is a dictionary with a key/value pair of object’s attributes. The ‘ __dict__ ’ attribute is not just limited to instances but can also be available to user-defined functions, modules, ...

How to get Dictionary of class instance attributes in Python?

Python Class - Get dictionary of class instance (__dict__ and vars) Python class instance has __dict__ method. We can get the dictionary of class instance attributes as follow. class Employee: def __init__(self, name, age): self.name = name self.age = age def hello(self): print ("I'm " + self.name + "."


2 Answers

The first part of your question is already answered by the linked answer: the __dict__ of instances is stored as a descriptor on the class. This is the A.__dict__['__dict__']. A.__dict__ on the other hand stores all the attributes of the A class - which itself is an instance of type. So actually it's type.__dict__['__dict__'] that provides these variables:

>>> type.__dict__['__dict__']
<attribute '__dict__' of 'type' objects>
>>> A.__dict__ == type.__dict__['__dict__'].__get__(A)
True

The reason why you're not seeing a __dict__ attribute on object is because it doesn't have one. This means you can't set instance variables on object instances:

>>> o = object()
>>> o.x = 1

AttributeError: 'object' object has no attribute 'x'

Similar behavior can be achieved for custom classes by defining __slots__:

>>> class B:
...     __slots__ = ()
... 
>>> vars(B)
mappingproxy({'__module__': '__main__', '__slots__': (), '__doc__': None})
>>> 
>>> b = B()
>>> b.x = 1

AttributeError: 'B' object has no attribute 'x'
like image 196
a_guest Avatar answered Oct 19 '22 17:10

a_guest


Firstly I want to say that I only partly know the answer to your question. The second part may not be entirely true on the behaviour of python. But first, I want to clear some things out: the docs you are quotings are concerning normal objects and may not apply on meta-classes as their internal behaviour is entirely coded in C.

vars(A)['dict']

As I understand how python works, I suspect the __dict__ you saw here:

>>> vars(A)['__dict__']                 #Value of '__dict__'
<attribute '__dict__' of 'A' objects>

I suspect it to be a sample for the __dict__ attribute of a future instance of the class. I don't have better answer for now but let's keep digging.

The __dict__ attribute on meta-classes

As object is a of class type is is pretty normal for it not to have a __dict__ as it is not possible to add attribute on basic types like int, float, or str. So why would these types have a __dict__ attribute if it is not used?

And finally, yes. There are restrictions on the __dict__ attribute of classes and meta-classes. These restrictions take form as the class MappingProxy like said in the vars documentation:

Objects such as modules and instances have an updateable __dict__ attribute; however, other objects may have write restrictions on their __dict__ attributes (for example, classes use a types.MappingProxyType to prevent direct dictionary updates).

But this behaviour is also explicitly said in the doc of the class object

Edit: I started to find good information about the wierd vars(A)['__dict__']. Take a look here

like image 2
eliottness Avatar answered Oct 19 '22 19:10

eliottness