What is the biggest difference between dir and __dict__ in python

class C(object): def f(self): print self.__dict__ print dir(self) c = C() cf() 

output:

 {} ['__class__', '__delattr__','f',....] 

why there is no "f" in itself .__ dict__

+45
source share
2 answers

dir() does much more than __dict__ search

First of all, dir() is an API method that knows how to use attributes of type __dict__ to find attributes of an object.

However, not all objects have the __dict__ attribute. For example, if you must add the __slots__ attribute to your own class, instances of this class will not have the __dict__ attribute, but dir() can still display the available attributes in these instances:

 >>> class Foo(object): ... __slots__ = ('bar',) ... bar = 'spam' ... >>> Foo().__dict__ Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'Foo' object has no attribute '__dict__' >>> dir(Foo()) ['__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__slots__', '__str__', '__subclasshook__', 'bar'] 

The same applies to many built-in types; list do not have the __dict__ attribute, but you can still list all the attributes with dir() :

 >>> [].__dict__ Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'list' object has no attribute '__dict__' >>> dir([]) ['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__delslice__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getslice__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__setslice__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort'] 

What dir() does with instances

Python instances have their own __dict__ , but their class:

 >>> class Foo(object): ... bar = 'spam' ... >>> Foo().__dict__ {} >>> Foo.__dict__.items() [('__dict__', <attribute '__dict__' of 'Foo' objects>), ('__weakref__', <attribute '__weakref__' of 'Foo' objects>), ('__module__', '__main__'), ('bar', 'spam'), ('__doc__', None)] 

The dir() method uses both of these __dict__ attributes, and one of them, object , to create a complete list of available attributes for the instance, class, and all ancestors of the class.

When you set attributes for a class, instances also see them:

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

because the attribute is added to the __dict__ class:

 >>> Foo.__dict__['ham'] 'eggs' >>> f.__dict__ {} 

Note that the __dict__ instance remains empty. A search for attributes of Python objects follows a hierarchy of objects from an instance to enter parent classes to search for attributes.

Only when you set the attributes directly in the instance will you see the attribute reflected in the __dict__ instance, while the __dict__ class remains unchanged:

 >>> f.stack = 'overflow' >>> f.__dict__ {'stack': 'overflow'} >>> 'stack' in Foo.__dict__ False 

TL; DR; or summary

dir() not just looking for an __dict__ object (which sometimes doesn’t even exist), it will use the object’s inheritance (its class or type and any superclasses or parents of that class or type) to provide you with a complete picture of all available attributes.

__dict__ instance is only a "local" set of attributes in this instance and does not contain all the attributes available in the instance. Instead, you also need to look at class and class inheritance inheritance.

+91
source

The function f belongs to a dictionary of class C c.__dict__ gives attributes specific to the C instance.

 >>> class C(object): def f(self): print self.__dict__ >>> c = C() >>> c.__dict__ {} >>> ca = 1 >>> c.__dict__ {'a': 1} 

c.__dict__ will give the attributes of class C , including the function f .

 >>> C.__dict__ dict_proxy({'__dict__': <attribute '__dict__' of 'C' objects>, '__module__': '__main__', '__weakref__': <attribute '__weakref__' of 'C' objects>, '__doc__': None, 'f': <function f at 0x0313C1F0>}) 

While an object can refer to an attribute of its class (and indeed of all ancestor classes), a class attribute, the so-called, does not become part of the associated dict itself . Thus, although it is legal access to the function f defined in class C as cf() , it does not appear as an attribute of C in c.__dict__ .

 >>> ca = 1 >>> c.__dict__ {'a': 1} 
+3
source

Source: https://habr.com/ru/post/1444994/


All Articles