假设我们这样做:
class thing(object):
pass
然后我做>>> thing.__eq__
,然后我得到<method-wrapper '__eq__' of type object at 0x0E8B68D0>
。但是如果我们这样做'__eq__' in dir(thing)
,我会得到一个NameError
说__eq__
未定义的异常,但如果它未定义,那么我如何获得方法包装返回,显然它已定义,但如果 dir 看不到它,它在哪里定义?
dir(thing)
返回方法名称列表,所有字符串。使用实际字符串进行测试:
'__eq__' in dir(thing)
这仍将返回False
,因为dir()
仅列出最重要方法的摘要。您还必须另外列出元类中的所有内容thing
,在这种情况下是type
:
>>> '__eq__' in dir(type(thing))
True
引用以下文档dir()
:
注意:因为主要是为了方便在交互式提示中使用
dir()
而提供的,所以它尝试提供一组有趣的名称,而不是尝试提供一组严格或一致定义的名称,并且其详细行为可能会随版本而变化。例如,当参数是类时,属性不在结果列表中。metaclass
强调我的。
__eq__
是这里的后备实现;type()
定义了一个合理的默认值(回退到一个身份测试,==
实现为is
),只要您的自定义类没有实现自定义版本,这并不有趣,列出它只会不必要地混淆dir()
.
原因是 Python 2 如何处理__eq__
. 检查此线程以获取更多信息。
在 python 3 中,事情发生了变化(不再有__cmp__
方法),并且'__eq__'
在返回的方法名称列表中dir(thing)
。
dir
没有列出所有属性:
文档说:
结果列表不一定是完整的......默认的 dir() 机制对不同类型的对象表现不同,因为它试图产生最相关的,而不是完整的信息......
因为提供 dir() 主要是为了方便在交互式提示下使用,所以它尝试提供一组有趣的名称,而不是尝试提供一组严格或一致定义的名称,并且它的详细行为可能会随版本而变化。例如,当参数是类时,元类属性不在结果列表中。
另外,我假设您已经测试过'__eq__' in dir(thing)
——注意引号——因为dir
返回了一个字符串列表。
ジョージ 展示了一种基于 rlcompleter 模块中的代码列出所有属性的方法:
import rlcompleter
def get_object_attrs(obj):
"""
based on code from the rlcompleter module
See https://stackoverflow.com/a/10313703/190597 (ジョージ)
"""
ret = dir(obj)
## if "__builtins__" in ret:
## ret.remove("__builtins__")
if hasattr(obj, '__class__'):
ret.append('__class__')
ret.extend(rlcompleter.get_class_members(obj.__class__))
ret = list(set(ret))
return ret
class Thing(object):
pass
print(get_object_attrs(Thing))
印刷
['__module__', '__format__', '__itemsize__', '__str__', '__reduce__', '__weakrefoffset__', '__dict__', '__sizeof__', '__weakref__', '__lt__', '__init__', '__setattr__', '__reduce_ex__', '__subclasses__', '__new__', '__abstractmethods__', '__class__', '__mro__', '__base__', '__bases__', '__dictoffset__', '__call__', '__doc__', '__ne__', '__getattribute__', '__instancecheck__', '__subclasscheck__', '__subclasshook__', '__gt__', '__name__', '__eq__', 'mro', '__basicsize__', '__flags__', '__delattr__', '__le__', '__repr__', '__hash__', '__ge__']
从中我们可以获得Thing
未列出的属性列表dir
:
>>> print(set(get_object_attrs(Thing)) - set(dir(Thing)))
set(['__ne__', '__abstractmethods__', '__subclasses__', '__eq__', '__instancecheck__', '__base__', '__flags__', '__mro__', '__le__', '__basicsize__', '__bases__', '__dictoffset__', '__weakrefoffset__', '__call__', '__name__', '__lt__', '__subclasscheck__', '__gt__', '__itemsize__', '__ge__', 'mro'])
get_class_members(cls)
cls
从和所有基中cls
收集属性。
因此,要获得更完整的属性列表,您必须添加dir
对象类的属性,以及对象类基的所有属性。