2

__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
4

1 に答える 1

4

実際、クラスのdir()関数には、 にリストされているすべてのクラスが既に含まれています__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__()

于 2012-10-31T09:02:31.267 に答える