python中dir和__dict__最大的区别是什么?
class C(object): def f(self): print self.__dict__ print dir(self) c = C() cf() 输出:
 {} ['__class__', '__delattr__','f',....] 
为什么自我中没有“f”.__ dict__
  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'] 
 这同样适用于许多内置types;  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上的object来创build实例,类和类的所有祖先上的可用属性的完整列表。 
在类上设置属性时,实例也会看到这些:
 >>> 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对象的属性查找遵循从实例到types到父类的对象的层次结构以search属性。 
 只有在实例上直接设置属性时,才会看到实例的__dict__中反映的属性,而类__dict__保持不变: 
 >>> f.stack = 'overflow' >>> f.__dict__ {'stack': 'overflow'} >>> 'stack' in Foo.__dict__ False 
TLDR; 或摘要
  dir()不只是查找一个对象的__dict__ (有时甚至不存在),它将使用该对象的传统(它的类或types,以及该类或types的任何超类或父类)给你所有可用属性的完整图片。 
 实例__dict__只是该实例上的“本地”属性集合,并不包含实例上可用的每个属性。 相反,您需要查看类和类的inheritance树。 
 函数f属于类C的字典。  c.__dict__产生特定于实例c属性。 
 >>> class C(object): def f(self): print self.__dict__ >>> c = C() >>> c.__dict__ {} >>> ca = 1 >>> c.__dict__ {'a': 1} 
  C.__dict__会产生C类的属性,包括函数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>}) 
 虽然一个对象可以引用它的类的属性(实际上是所有的祖先类),但是被引用的类属性并不会成为关联的字典本身的一部分。 因此,虽然它是合法的访问函数f在类C定义为cf() ,但它不会在c.__dict__作为c的属性出现。 
 >>> ca = 1 >>> c.__dict__ {'a': 1}