有没有之间的差异dir(…),并vars(…).keys()在Python?
(我希望会有区别,因为否则会破坏“一种方法”的原则... :)
有没有之间的差异dir(…),并vars(…).keys()在Python?
(我希望会有区别,因为否则会破坏“一种方法”的原则... :)
Answers:
Python对象将其实例变量存储在属于该对象的字典中。vars(x)返回此字典(与一样x.__dict__)。dir(x)另一方面,返回的字典,其中包含x“属性,其类的属性,以及递归其类的基类的属性”。
当您使用点运算符访问对象的属性时,Python所做的不仅仅是在该对象字典中查找该属性。一个常见的情况是whenx是class的实例,C而您调用其方法m:
class C:
def m(self):
print("m")
x = C()
x.m()
该方法m未存储在中x.__dict__。它是类的一个属性C。
当您调用时x.m(),Python将从min中开始查找x.__dict__,但找不到它。但是,它知道x是的一个实例C,因此它将接下来查找,在其中C.__dict__找到它,并m以x作为第一个参数进行调用。
因此,vars(x)和之间的区别在于,在类的类(及其基类)中查找可以从中访问的属性,而不仅仅是存储在自己的符号表中的那些属性,dir(x)这需要dir(x)做额外的工作。在上面的示例中,由于没有实例变量,因此返回空字典。但是,回报xxvars(x)xdir(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']
dir()还会返回广告位,而vars()不会返回。
dir可以通过实现__dir__magic方法自定义的输出:class A: def __dir__(self): return ['a']然后您拥有dir(A()) == ['a']while vars(A()) == {}。
该文档的内容dir如下:
不带参数的情况下,返回当前本地范围内的名称列表。使用一个参数,尝试返回该对象的有效属性列表。
关于vars:
不带参数的情况下,返回与当前本地符号表相对应的字典。使用模块,类或类实例对象作为参数(或具有
__dict__属性的任何其他对象),返回与该对象的符号表相对应的字典。
如果您看不到差异,则可能会显示更多(分组以便于阅读):
>>> 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__'])
如果您不想通读,请dir在vars不包含以下属性的情况下:
>>> set(dir(list)) - vars(list).keys()
{'__class__', '__delattr__', '__dir__', '__format__', '__init_subclass__',
'__reduce__', '__reduce_ex__', '__setattr__', '__str__', '__subclasshook__'}
另请注意,dir()的输出按字母顺序排序,而vars()的输出则按定义属性的顺序排序。
除了给出的答案外,我还要补充一点,将vars()与实例内置类型一起使用会产生错误,因为实例内置类型没有__dict__属性。
例如。
In [96]: vars([])
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-96-a6cdd8d17b23> in <module>()
----> 1 vars([])
TypeError: vars() argument must have __dict__ attribute
__dict__属性。感谢您纠正我。我已经更新了答案。