0

假设我们这样做:

class thing(object):
    pass

然后我做>>> thing.__eq__,然后我得到<method-wrapper '__eq__' of type object at 0x0E8B68D0>。但是如果我们这样做'__eq__' in dir(thing),我会得到一个NameError__eq__未定义的异常,但如果它未定义,那么我如何获得方法包装返回,显然它已定义,但如果 dir 看不到它,它在哪里定义?

4

3 回答 3

2

dir(thing)返回方法名称列表,所有字符串。使用实际字符串进行测试:

'__eq__' in dir(thing) 

这仍将返回False,因为dir()仅列出最重要方法的摘要。您还必须另外列出元类中的所有内容thing,在这种情况下是type

>>> '__eq__' in dir(type(thing))
True

引用以下文档dir()

注意:因为主要是为了方便在交互式提示中使用dir()而提供的,所以它尝试提供一组有趣的名称,而不是尝试提供一组严格或一致定义的名称,并且其详细行为可能会随版本而变化。例如,当参数是类时,属性不在结果列表中。metaclass

强调我的。

__eq__是这里的后备实现;type()定义了一个合理的默认值(回退到一个身份测试,==实现为is),只要您的自定义类没有实现自定义版本,这并不有趣,列出它只会不必要地混淆dir().

于 2013-08-12T13:15:26.057 回答
1

原因是 Python 2 如何处理__eq__. 检查此线程以获取更多信息。

在 python 3 中,事情发生了变化(不再有__cmp__方法),并且'__eq__' 返回的方法名称列表中dir(thing)

于 2013-08-12T13:47:58.513 回答
1

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对象类的属性,以及对象类基的所有属性。

于 2013-08-12T13:15:38.387 回答