私も最近同じことを疑問に思っていました。mro
私は、「Pythonの実装の原因は何ですか/__mro__
にリストされていませんdir
か?そして、リストするために何を信頼できますdir
か?」に沿った回答を探していました。mro
単純に「Python のドキュメントはinを含めないことをどのように正当化しdir
ますか?」よりも プログラミング言語の動作に対する私の期待が実際の動作と一致しない場合、それは言語の理解が正しくないことを意味するため、好きではありません-それが単なるバグでない限りurllib2.escape
. それで、答えがわかるまで、少し掘り下げました。
上記のコメントのドキュメントから引用された adolfopa 行は、dir の動作を説明するのに適しています。
「オブジェクトがタイプまたはクラス オブジェクトの場合、リストにはその属性の名前と、そのベースの属性が再帰的に含まれます。」
これは何を意味するのでしょうか?クラスとその各スーパークラスdir
から属性を再帰的に収集します。__dict__
__dict__
set(dir(object)) == set(dict(object.__dict__).keys() #True
class A(object):
...
class B(object):
...
class C(B):
...
class D(C,A):
...
set(dir(D)) == set(D.__dict__.keys()) + set(C.__dict__.keys()) \
+ set(B.__dict__.keys()) + set(A.__dict__.keys()) \
+ set(object.__dict__.keys()) #True
dir(object)
リストされていない理由は__mro__
、mro
オブジェクトの属性ではないためです。それらは の属性ですtype
。それ自身を定義しないすべてのクラス__metaclass__
は のインスタンスですtype
。ほとんどのメタクラス サブクラスtype
. このようなメタクラスのインスタンスも同様に型のインスタンスです。MyClass.__mro__
と同じtype.__getattribute__(MyClass,'__mro__')
です。
Python がクラスを実装する方法は、必然的に dir の動作に関してわずかな異常を生み出します。
通常、dir(MyClass) == dir(MyClass(*requiredparameters)) #True
.
ただし、dir(type) == dir(type(*requiredparameters)) #False
これがそうでない可能性がある唯一の方法は、type.__dict__
とdir
が同じである場合でした。これは、自明のことですが、 の目的ではありませんdir
。
ちょっと待って!は再帰的な合計によって作成されますが、その最後の部分を変更して、それがただではなく になるdir
ようにできないのはなぜですか。そうすれば、/と、クラス オブジェクトが持つ他のすべての属性を持ちますか? ああ、でもそれらはクラスではなく、クラス オブジェクトの属性になります。さて、違いは何ですか?dir(object)
object.__dict__.keys()
object.__dict__.keys() + type.__dict__.keys()
mro
__mro__
検討
list.__mro__ #(<type 'list'>, <type 'object'>)
一方
[].__mro__
# Traceback (most recent call last):
# File "<stdin>", line 1, in <module>
# AttributeError: 'list' object has no attribute '__mro__'
dir
これで、何をリストに載せることが期待でき、何をリストに載せないことが期待できるかを答えるのに適した場所にdir
います. 簡単な答えは、すでに説明したものです。__dict__
クラスのすべてのキーとそのスーパークラスのそれぞれのすべてのキーを__dict__
再帰的にリストします。インスタンスの場合、インスタンスの .xml にあるすべてのパラメータも含まれます__dict__
。負のスペースを埋めるために、 で定義されている__getattr__
もの__getattribute__
も、__dict__
. また、タイプ/メタタイプの属性もリストしません。
私が指摘しなければならないと思うもう1つのこと:私がこれを書いている時点で受け入れられている回答であるダンの回答には、不正確または少なくとも誤解を招く情報が含まれています。
組み込みオブジェクトの属性は設定できないため、ある意味でtype.__mro__
は「読み取り専用」ですが、それと同じ方法でのみlist.append
ですtype.mro
。
MyClass.__mro__ = "Hello world!"
エラーにはなりません。で定義されているメソッド解決順序には影響しませんtype
。そのため、その動作を変更しようとしても、期待した効果が得られない場合があります。(Python でクラスの属性を定義する方法はこのように機能するため、これが行うことは、予想さMyClass(*requiredparameters).__mro__
れる"Hello World!"
はずだったものになります。)__mro__
メタクラスを作成するために型をサブクラス化するときにオーバーライドすることもできます。オーバーライドしない場合は、オーバーライドしない他のものと同様に継承されます。(型のサブクラスではなく、型のインスタンスを返す関数ではないメタクラスを作成している場合は、おそらく、自分が何をしているのかを十分に理解しているので、これについて心配する必要はありません。しかし__mro__
サブクラス化していないため、継承されませんtype
)
ドキュメント(スーパーの動作を説明)によると:
型の __mro__ 属性には、getattr() と super() の両方で使用されるメソッド解決の検索順序がリストされています。この属性は動的であり、継承階層が更新されるたびに変更される可能性があります。
したがって、直接変更する__mro__
と、変更とほぼ同じように、期待どおりに動作するはずmro
です。ただし、通常は、関数をオーバーライドすることで目的の動作を取得する方が簡単です。(サブクラス化を適切に処理するために何をする必要があるかを考えてください。)