1

官方文档

如果对象有一个名为 的方法__dir__(),该方法将被调用并且必须返回属性列表。这允许实现自定义__getattr__()__getattribute__()功能的对象自定义dir()报告其属性的方式。

如果自定义__dir__实现,由另一个函数返回的结果inspect.getmembers()也会受到影响。

例如:

class С(object):
    __slots__ = ['atr']
    def __dir__(self):
        return ['nothing']
    def method(self):
        pass
    def __init__(self):
        self.atr = 'string'

c = C() 
print dir(f) #If we try this - well get ['nothing'] returned by custom __dir__()
print inspect.getmembers(f) #Here we get []
print f.__dict__ #And here - exception will be raised because of __slots__

在这种情况下,如何获取对象名称列表?

4

2 回答 2

4

回答原始问题- 是否inspect.getmembers()使用__dir__()like dir()does?

这是源代码,inspect.getmembers()因此我们可以看到它的实际作用:

def getmembers(object, predicate=None):
    """Return all members of an object as (name, value) pairs sorted by name.                                                                                                                                     
    Optionally, only return members that satisfy a given predicate."""
    results = []
    for key in dir(object):
        try:
            value = getattr(object, key)
        except AttributeError:
            continue
        if not predicate or predicate(value):
            results.append((key, value))
    results.sort()
    return results

从这里我们看到它正在使用dir()并且只是对结果进行了一些过滤。

如何获取具有覆盖的属性__dir__()

根据这个答案,不可能总是得到一个完整的属性列表,但在某些情况下我们仍然可以肯定地得到它们/得到足够有用的东西。

文档

如果对象不提供__dir__(),则该函数会尽力从对象的__dict__属性(如果已定义)及其类型对象中收集信息。结果列表不一定完整,并且当对象具有 custom 时可能不准确__getattr__()

因此,如果您不使用__slots__,您可以查看您的对象(以及它的类型对象)以获得通常会提供给您__dict__的基本相同的信息。dir()因此,就像 with 一样dir(),您必须使用更严格的方法来获取元类方法。

如果您正在使用__slots__,那么在某种程度上,获取类属性会更简单一些。是的,没有字典,但有它__slots__自己,它包含所有属性的名称。例如,添加print c.__slots__到您的示例代码会产生['atr']. (同样,需要更严格的方法来获取超类的属性。)

如何获取方法

根据用例,您可能需要不同的解决方案,但如果您只是想轻松找出方法,您可以简单地使用内置的help().

修改后的 PyPydir()

这是上述某些方法的替代方案:要获得dir()忽略用户定义__dir__方法的版本,您可以只采用PyPy 的实现dir()删除引用__dir__方法的部分。

于 2012-12-16T05:15:13.960 回答
0

正如马修在另一个答案中指出的那样,getmembers显然返回的dir是实际属性的结果子集。

>>> class C:
>>>   def foo(self):
>>>     pass
>>>   def __dir__(self):
>>>     return ['test']
>>>
>>> import inspect
>>> c = C()
>>> dir(c)
['test']
>>> inspect.getmembers(c)
[]
于 2012-12-16T05:15:27.763 回答