私はこれらのような投稿を読みました:
しかし、どういうわけか私は混乱しました。次のような多くの混乱:
いつ、なぜ私は次のようなことをしなければならないのですか?
# Refer link1
return super(MyType, cls).__new__(cls, name, bases, newattrs)
または
# Refer link2
return super(MetaSingleton, cls).__call__(*args, **kw)
または
# Refer link2
return type(self.__name__ + other.__name__, (self, other), {})
スーパーはどのように正確に機能しますか?
Link1のクラスレジストリとunregistryとは何ですか?また、どのように正確に機能しますか? (私はそれが singleton と関係があると思いました。私は間違っているかもしれません、Cのバックグラウンドからです。私のコーディングスタイルはまだ機能とOOの混合です)。
クラスのインスタンス化(サブクラス、メタクラス、スーパー、タイプ)とメソッド呼び出し(
metaclass->__new__, metaclass->__init__, super->__new__, subclass->__init__ inherited from metaclass
)適切にコメントされた作業コードを使用します(最初のリンクは非常に近いですが、clsキーワードとsuper(..)およびレジストリについては説明していません)。できれば多重継承の例。
追伸:Stack Overflowのフォーマットでテキストが変換されていたため、最後の部分をコードとして作成しましたmetaclass->__new__
to metaclass->new
OK、ここではかなりの数のコンセプトをミックスに取り入れました!私はあなたが持っている特定の質問のいくつかを引き出すつもりです。
一般に、Pythonの最後の数バージョンでこのトリッキーな領域に多くの変更が加えられたため、super、MRO、およびmetclassesの理解ははるかに複雑になります。
Python独自のドキュメント は非常に優れたリファレンスであり、完全に最新です。 IBMdeveloperWorksの記事 があります。これは紹介としては問題なく、よりチュートリアルベースのアプローチを採用していますが、5年前のものであり、話すのに多くの時間を費やしていることに注意してください。メタクラスへの古いスタイルのアプローチについて。
super
は、オブジェクトのスーパークラスにアクセスする方法です。これは、主にPythonでの多重継承のために、(たとえば)Javaのsuper
キーワードよりも複雑です。 Super Thoughd Harmful が説明しているように、super()
を使用すると、スーパークラスのチェーンを暗黙的に使用することになります。その順序は/で定義されます。 メソッド解決順序 (MRO)。
(インスタンスではなく)クラスでmro()
を呼び出すことにより、クラスのMROを簡単に確認できます。メタクラスはオブジェクトのスーパークラス階層にないことに注意してください。
Thomas 'メタクラスの説明 here は優れています:
メタクラスは、クラスのクラスです。クラスがクラスのインスタンスの動作を定義するように、メタクラスはクラスの動作を定義します。クラスはメタクラスのインスタンスです。
あなたが与える例では、これが起こっていることです:
___new__
_への呼び出しは、MROの次のことまでバブルアップされています。この場合、super(MyType, cls)
はtype
に解決されます。 _type.__new__
_を呼び出すと、Pythonは、通常のインスタンス作成手順を完了します。
この例では、メタクラスを使用してシングルトンを適用しています。彼はメタクラスの___call__
_をオーバーライドしているので、クラスインスタンスが作成されるたびにそれをインターセプトし、インスタンスの作成が既に存在する場合はそれをバイパスできます(_cls.instance
_に格納されます)。メタクラスで___new__
_をオーバーライドするだけでは十分ではないことに注意してください。これは、クラスを作成するときにのみ呼び出されるためです。ただし、クラスで___new__
_をオーバーライドすると機能します。
これは、クラスを動的に作成する方法を示しています。これは、提供されたクラスの名前を作成されたクラス名に追加し、それをクラス階層にも追加しているところです。
探しているコード例の種類は正確にはわかりませんが、メタクラス、継承、メソッド解決を示す簡単な例を次に示します。
_class MyMeta(type):
def __new__(cls, name, bases, dct):
print "meta: creating %s %s" % (name, bases)
return type.__new__(cls, name, bases, dct)
def meta_meth(cls):
print "MyMeta.meta_meth"
__repr__ = lambda c: c.__name__
class A(object):
__metaclass__ = MyMeta
def __init__(self):
super(A, self).__init__()
print "A init"
def meth(self):
print "A.meth"
class B(object):
__metaclass__ = MyMeta
def __init__(self):
super(B, self).__init__()
print "B init"
def meth(self):
print "B.meth"
class C(A, B):
__metaclass__ = MyMeta
def __init__(self):
super(C, self).__init__()
print "C init"
>>> c_obj = C()
meta: creating A (<type 'object'>,)
meta: creating B (<type 'object'>,)
meta: creating C (A, B)
B init
A init
C init
>>> c_obj.meth()
A.meth
>>> C.meta_meth()
MyMeta.meta_meth
>>> c_obj.meta_meth()
Traceback (most recent call last):
File "mro.py", line 38, in <module>
c_obj.meta_meth()
AttributeError: 'C' object has no attribute 'meta_meth'
_
これがより実用的な答えです。
それはめったに重要ではありません
" Pythonのメタクラスとは "。結論として、type
はすべてのクラスのメタクラスです。これはほとんど実用的ではありません。
class X(object):
pass
type(X) == type
" Pythonのメタクラスの(具体的な)ユースケースは何ですか? "。結論。無し。
" PythonのSuperは気の利いたものですが、使用できません "。興味深いメモですが、実用的な価値はほとんどありません。複雑な多重継承ネットワークを解決する必要はありません。多重継承の代わりに明示的なStrategy設計を使用することで、この問題の発生を簡単に防ぐことができます。
これが、過去7年間のPythonプログラミングの経験です。
クラスには、私のクラスからobject
への単純なチェーンを形成する1つ以上のスーパークラスがあります。
「クラス」の概念は、type
という名前のメタクラスによって定義されます。 「クラス」の概念を拡張したいと思うかもしれませんが、これまでのところ、実際には実現していません。一度もありません。 type
は常に正しいことをします。
super
の使用は、実際には非常にうまく機能します。これにより、サブクラスはそのスーパークラスに従うことができます。これらのメタクラスの例では、組み込みのメタクラスtype
を拡張しているため、たまたま表示されます。
ただし、すべてのサブクラスの状況で、super
を使用してスーパークラスを拡張します。
メタクラス
メタクラスの問題は次のとおりです。
すべてのオブジェクトには、その型定義、つまり「クラス」への参照があります。
class
は、それ自体がオブジェクトでもあります。
したがって、タイプclass
のオブジェクトには、そのタイプまたは「クラス」への参照があります。 「クラス」の「クラス」はメタクラスです。
「クラス」はC++ランタイムオブジェクトではないため、これはC++では発生しません。 Java、Smalltalk、Pythonで発生します。
メタクラスは、クラスオブジェクトの動作を定義します。
クラスとのやり取りの90%は、クラスに新しいオブジェクトを作成するように依頼することです。
10%の確率で、クラスメソッドまたはクラス変数(C++では「静的」またはJava用語))を使用します。
クラスレベルのメソッドのユースケースをいくつか見つけました。クラス変数のユースケースはほとんどありません。オブジェクトの構築方法を変更する状況はこれまでありませんでした。