说我们这样做:
class thing(object):
pass
然后我>>> thing.__eq__
,然后我得到<method-wrapper '__eq__' of type object at 0x0E8B68D0>
。但是如果我们执行'__eq__' in dir(thing)
,我会得到一个NameError
异常,说明__eq__
没有定义,但是如果它没有定义,那我怎么得到一个方法包装返回,显然是它定义的,但如果dir看不到它,它在哪里定义?
答案 0 :(得分:2)
dir(thing)
返回方法名称的列表,所有字符串。使用实际字符串进行测试:
'__eq__' in dir(thing)
这仍将返回False
,因为dir()
仅列出了最重要方法的摘要。您还必须在thing
的元类上另外列出所有内容,在本例中为type
:
>>> '__eq__' in dir(type(thing))
True
引用dir()
的文档:
注意:因为提供
dir()
主要是为了方便在交互式提示中使用,所以它会尝试提供一个有趣的 一组名称超过它试图严格或一致地提供 定义的名称集,其详细行为可能会发生变化 版本。例如,metaclass
属性不在结果中 列表当参数是一个类时。
强调我的。
__eq__
是此处的后备实施; type()
定义了一个合理的默认值(退回到身份测试,==
实现为is
),只要您的自定义类没有实现自定义版本,即没有意思并列出它只会不必要地混淆dir()
的结果。
答案 1 :(得分:1)
dir
未列出所有属性:
The docs说:
结果列表不一定完整...... 默认的dir()机制对不同类型的行为有所不同 对象,因为它试图产生最相关的,而不是 完整,信息......
因为提供dir()主要是为了方便使用 交互式提示,它试图提供一组有趣的名称 不只是它试图提供严格或一致定义的集合 名称及其详细行为可能会在不同版本中发生变化。对于 例如,元类属性不在结果列表中 论证是一个阶级。
此外,我假设您测试了'__eq__' in dir(thing)
- 请注意引号 - 因为dir
会返回字符串列表。
ジョージ shows根据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
的所有基础。
因此,要获得更完整的属性列表,必须将{{1}}添加到对象类的属性,以及对象类的基础的所有属性。
答案 2 :(得分:1)
原因是Python 2如何处理__eq__
。
请查看this thread以获取更多信息。
在python 3中,'__eq__'
返回的方法名称列表中的内容发生了变化(no more __cmp__
method)和dir(thing)
。