小编典典

python中dir和__dict__之间的最大区别是什么

python

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

输出:

{}

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

为什么自我中不存在“ f”。dict


阅读 241

收藏
2020-12-20

共1个答案

小编典典

dir() 不仅仅是查找 __dict__

首先,dir()是一种API方法,它知道如何使用属性__dict__来查找对象的属性。

但是,并非所有对象都具有__dict__属性。例如,如果要向自定义类添加__slots__属性,则该类的实例将没有__dict__属性,但dir()仍可以列出这些实例上的可用属性:

>>> 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']

同样适用于许多内置类型。list没有__dict__属性,但是您仍然可以使用列出所有属性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']

dir()实例有什么用

Python实例具有自己的__dict__,但它们的类也有:

>>> 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)]

dir()方法使用 两种 这些__dict__属性, 并且 一来就object上创建实例,类可用属性的完整列表,并在类的所有祖先。

在类上设置属性时,实例也会看到以下内容:

>>> 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'

因为该属性已添加到类中__dict__

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

注意实例如何__dict__留空。在Python对象上进行属性查找遵循对象的层次结构,从实例到类型,再到父类,以搜索属性。

仅当直接在实例上设置属性时,您才可以在实例保持不变__dict__的情况下看到反映在实例中的属性__dict__

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

TLDR;或摘要

dir()不仅查找对象__dict__(有时甚至不存在),它还将使用对象的遗产(其类或类型,以及该类或类型的任何超类或父级)为您提供完整的图像所有可用的属性。

实例__dict__只是该实例上的“本地”属性集,并不包含该实例上可用的每个属性。相反,您还需要查看类和类的继承树。

2020-12-20