考虑一下:
>>> import math
>>> dir(math)
['__doc__', '__name__', '__package__', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atan2', 'atanh', 'ceil', 'copysign', 'cos', 'cosh', 'degrees', 'e', 'exp', 'fabs', 'factorial', 'floor', 'fmod', 'frexp', 'fsum', 'hypot', 'isinf', 'isnan', 'ldexp', 'log', 'log10', 'log1p', 'modf', 'pi', 'pow', 'radians', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'trunc']
__dict__
未列出,但我仍然可以
>>> math.__dict__
与
相同>>> class MyClass(object):
def __init__(self, var1, var2):
self.a = var1
self.b = var2
def __call__(self, arg):
print " The arg passed is ", arg
>>> dir(MyClass)
['__call__', '__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']
__bases__
和__base__
未列出,但我仍然可以:
>>> MyClass.__bases__
(<type 'object'>,)
>>> MyClass.__base__
<type 'object'>
问题:
如何预先知道或告知从python对象可以访问的所有属性?在这种情况下,我如何判断math
模块__dict__
和MyClass
有__base__
和__bases__
?
答案 0 :(得分:2)
如果您正在寻找完全一般的东西,则无法做到这一点,因为属性查找是动态的。正如the docs所说:
尝试返回该对象的有效属性列表。
关键词是“尝试”。下面是:
注意因为dir()主要是为了方便在交互式提示中使用而提供的,所以它尝试提供一组有趣的名称而不是尝试提供严格或一致定义的名称集,并且其详细行为可能跨版本更改。例如,当参数是类时,元类属性不在结果列表中。
实际上,它可以做的只是查看对象的__dict__
,它的类型以及该类型的任何基类。 (然后它减去了一些东西 - 例如,跳过类型类型的属性以避免暴露元类属性,这通常是你不关心的)。如果您需要确切的详细信息,请阅读上面链接的文档。
同时,如果对象具有__getattr__
/ __setattr__
/ __delattr__
,或__getattribute__
,或上述的C-API等价物,则它可能具有各种属性不在任何字典中,甚至可能是无限的字典。例如:
class C(object):
def __getattr__(self, name):
return name
c = C()
print(c.a)
这将打印出a
。但dir
怎么可能知道c.a
存在?即使它可以解释我的代码,它也必须打印出所有可能字符串的列表,这显然是你不想要的。
还有一些特殊的属性名称,这些属性名称在解释器的封面下以花哨的方式处理。
此外,任何对象都可以定义__dir__
方法来返回它想要的任何内容。
如果你正在寻找特定的东西,你可能会这样做。例如,如果您只是尝试获取属性而不减去元类属性,那只是dir(x) + dir(type(x))
,或者更好,dir(x) + [a for a in dir(type(x)) if a not in dir(x)]
(删除重复项)。
但是如果你想知道一个对象的所有属性,那么你就不能。