简体   繁体   English

Python 中 dir(...) 和 vars(...).keys() 的区别?

[英]Difference between dir(…) and vars(…).keys() in Python?

Is there a difference between dir(…) and vars(…).keys() in Python? Python 中的dir(…)vars(…).keys()有区别吗?

(I hope there is a difference, because otherwise this would break the "one way to do it" principle... :) (我希望有区别,否则这会打破“一种方法”的原则...... :)

Python objects usually store their instance variables in a dictionary that belongs to the object (except for slots). Python 对象通常将它们的实例变量存储在属于该对象的字典中(槽除外)。 vars(x) returns this dictionary (as does x.__dict__ ). vars(x)返回这个字典(和x.__dict__ )。 dir(x) , on the other hand, returns a dictionary of x 's "attributes, its class's attributes, and recursively the attributes of its class's base classes."另一方面, dir(x)返回一个包含x的“属性、其类的属性,并递归地返回其类的基类的属性”的字典。

When you access an object's attribute using the dot operator, Python does a lot more than just look up the attribute in that objects dictionary.当您使用点运算符访问对象的属性时,Python 所做的不仅仅是在该对象字典中查找属性。 A common case is when x is an instance of class C and you call its method m :一个常见的情况是当x是类C一个实例并且你调用它的方法m

class C:
    def m(self):
        print("m")
    
x = C()
x.m()

The method m is not stored in x.__dict__ .方法m不存储在x.__dict__ It is an attribute of the class C .它是类C一个属性。

When you call xm() , Python will begin by looking for m in x.__dict__ , but it won't find it.当您调用xm() ,Python 将首先在x.__dict__ m ,但它不会找到它。 However, it knows that x is an instance of C , so it will next look in C.__dict__ , find it there, and call m with x as the first argument.然而,它知道xC一个实例,所以它接下来会在C.__dict__ ,在那里找到它,并以x作为第一个参数调用m

So the difference between vars(x) and dir(x) is that dir(x) does the extra work of looking in x 's class (and itsbases ) for attributes that are accessible from it, not just those attributes that are stored in x 's own symbol table.所以vars(x)dir(x)之间的区别在于dir(x)做了额外的工作,在x的类(及其类)中查找可从中访问的属性,而不仅仅是那些存储的属性在x自己的符号表中。 In the above example, vars(x) returns an empty dictionary, because x has no instance variables.在上面的例子中, vars(x)返回一个空字典,因为x没有实例变量。 However, dir(x) returns但是, dir(x)返回

['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', 
'__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', 
'__init__', '__init_subclass__', '__le__', '__lt__', '__module__', 
'__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', 
'__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 
'm']

The documentation has this to say about dir :文档中有关于dir

Without arguments, return the list of names in the current local scope.不带参数,返回当前本地范围内的名称列表。 With an argument, attempt to return a list of valid attributes for that object.使用参数,尝试返回该对象的有效属性列表。

And this about vars :这关于vars

Without arguments, return a dictionary corresponding to the current local symbol table.不带参数,返回与当前本地符号表对应的字典。 With a module, class or class instance object as argument (or anything else that has a __dict__ attribute), returns a dictionary corresponding to the object's symbol table.使用模块、类或类实例对象作为参数(或任何其他具有__dict__属性的东西),返回对应于对象符号表的字典。

If you don't see the difference, maybe this will show you more (grouped for easier reading):如果您没有看到差异,也许这会向您展示更多信息(分组以便于阅读):

>>> dir(list)
['__add__', '__class__', '__class_getitem__', '__contains__', '__delattr__', 
'__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', 
'__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', 
'__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', 
'__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', 
'__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', 
'__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 
'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
>>> vars(list).keys()
dict_keys(['__repr__', 
'__hash__', 
'__getattribute__', 
'__lt__', '__le__', '__eq__', '__ne__', '__gt__', '__ge__', 
'__iter__', 
'__init__', 
'__len__', 
'__getitem__', '__setitem__', '__delitem__', 
'__add__', '__mul__', '__rmul__', '__contains__', '__iadd__', '__imul__', 
'__new__', 
'__reversed__', '__sizeof__', 
'clear', 'copy', 'append', 'insert', 'extend', 'pop', 'remove', 'index', 'count', 'reverse', 'sort', 
'__class_getitem__', 
'__doc__'])

If you don't feel like reading through that, dir includes these attributes while vars does not:如果您不想通读, dir包含这些属性,而vars不包含:

>>> set(dir(list)) - vars(list).keys()
{'__class__', '__delattr__', '__dir__', '__format__', '__init_subclass__', 
'__reduce__', '__reduce_ex__', '__setattr__', '__str__', '__subclasshook__'}

Note also that dir() 's output is sorted alphabetically, whereas vars() 's output is sorted by the order the attributes were defined in.另请注意, dir()的输出按字母顺序排序,而vars()的输出按属性定义的顺序排序。

Apart from Answers given, I would like to add that, using vars() with instances built-in types will give error, as instances builtin types do not have __dict__ attribute.除了给出的答案之外,我想补充一点,将 vars() 与实例内置类型一起使用会出错,因为实例内置类型没有__dict__属性。

eg.例如。

In [96]: vars([])
---------------------------------------------------------------------------

TypeError Traceback (most recent call last)
<ipython-input-96-a6cdd8d17b23> in <module>()
      ----> 1 vars([])
TypeError: vars() argument must have __dict__ attribute

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM