我找到了以下功能,但我不知道为什么需要进行额外的__bases__
扫描:
def getMembersWithBases(classType):
members = set(dir(classType))
# recursive bases scan
for baseClassType in classType.__bases__:
members.update(getMembersWithBases(baseClassType))
return members
以下功能更快并且结果相同 - 那么为什么需要进行额外的__bases__
扫描呢?
def getMembers(classType):
members = set(dir(classType))
return members
一些包含新旧类的测试代码:
class Father(object):
def testFather():
pass
class Mother(object):
def testMother():
pass
class Child(Father, Mother):
def testChild():
pass
print type(Child)
print getMembers(Child) == getMembersWithBases(Child)
class Father:
def testFather():
pass
class Mother:
def testMother():
pass
class Child(Father, Mother):
def testChild():
pass
print type(Child)
print getMembers(Child) == getMembersWithBases(Child)
结果:
<type 'type'>
True
<type 'classobj'>
True
答案 0 :(得分:4)
确实,对于类,dir()
function已经包含__bases__
中列出的所有类:
如果对象是类型或类对象,则列表包含其属性的名称,并且递归地包含其基础的属性。
但是,通过指定__dir__
方法(通过元类,类方法是不够的),类可以覆盖该行为:
如果对象具有名为
__dir__()
的方法,则将调用此方法,并且必须返回属性列表。
当存在__dir__()
方法时,__bases__
不会被递归:
>>> class Foo(object):
... def spam(self): pass
...
>>> class Bar(object):
... def ham(self): pass
...
>>> class CustomDirMetaclass(type):
... def __dir__(cls):
... return ['eggs']
...
>>> class Baz(Foo, Bar):
... __metaclass__ = CustomDirMetaclass
... def eggs(self): pass
...
>>> dir(Baz)
['eggs']
>>> getMembers(Baz)
set(['eggs'])
>>> getMembersWithBases(Baz)
set(['__module__', '__getattribute__', 'eggs', '__reduce__', '__subclasshook__', '__dict__', '__sizeof__', '__weakref__', '__init__', 'ham', '__setattr__', '__reduce_ex__', '__new__', 'spam', '__format__', '__class__', '__doc__', '__delattr__', '__repr__', '__hash__', '__str__'])
因此,__bases__
类方法中getMembersWithBases()
的显式递归可能是绕过任何自定义__dir__()
实现的尝试。
否则,__bases__
上的递归完全是多余的。
在我个人看来,__bases__
的递归甚至是,如果 __dir__()
方法存在于类层次结构中。在这种情况下,__dir__()
方法覆盖是错误的,因为 方法应该递归__bases__
中列出的类以正确模仿dir()
函数的行为
说实话,我怀疑你找到的函数的作者并不知道dir()
的递归性质,并且针对__bases__
递归添加,而不是作为绕过自定义的手段__dir__()
方法。