29

私はこれらのような投稿を読みました:

  1. Pythonのメタクラスとは何ですか?
  2. Pythonでのメタクラスの(具体的な)ユースケースは何ですか?
  3. Pythonのスーパーは気の利いたものですが、使用することはできません

しかし、どういうわけか私は混乱しました。次のような多くの混乱:

いつ、なぜ私は次のようなことをしなければならないのですか?

# 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のクラスレジストリとアンレジストリとは何ですか?それはどのように正確に機能しますか?(私はそれがシングルトンと関係があると思いました。私は間違っているかもしれません、Cのバックグラウンドからです。私のコーディングスタイルはまだ機能とOOの混合です)。

クラスのインスタンス化(サブクラス、メタクラス、スーパー、タイプ)とメソッド呼び出し(

metaclass->__new__, metaclass->__init__, super->__new__, subclass->__init__ inherited from metaclass

)適切にコメントされた作業コードを使用します(最初のリンクは非常に近いですが、clsキーワードとsuper(..)およびレジストリについては説明していません)。できれば多重継承の例。

PS:Stack Overflowのフォーマットでテキストmetaclass->__new__ がメタクラスに変換されていたため、最後の部分をコードとして作成しました-> new

4

2 に答える 2

24

OK、ここでかなりの数の概念をミックスに投入しました! 皆様から寄せられた具体的なご質問を抜粋してご紹介します。

一般に、super、MRO、および metclasses を理解することは、Python の最後のいくつかのバージョンでこの扱いにくい領域に多くの変更が加えられたため、はるかに複雑になっています。

Python 自身のドキュメントは非常に優れたリファレンスであり、完全に最新のものです。入門としては適切で、よりチュートリアルベースのアプローチをとるIBM developerWorks の記事がありますが、それは 5 年前のものであり、メタクラスに対する古いスタイルのアプローチについて多くの時間を費やしていることに注意してください。

superオブジェクトのスーパークラスにアクセスする方法です。super主に Python の多重継承のため、(たとえば) Java のキーワードよりも複雑です。Super Considered Harmfulが説明しているように、使用すると、メソッド解決順序(MRO)super()によって定義される順序であるスーパークラスのチェーンを暗黙的に使用することになります。

mro()(インスタンスではなく) クラスを呼び出すことにより、クラスの MRO を簡単に確認できます。メタクラスはオブジェクトのスーパークラス階層には含まれないことに注意してください。

ここでのThomasのメタクラスの説明は優れています。

メタクラスはクラスのクラスです。クラスがクラスのインスタンスの動作を定義するように、メタクラスはクラスの動作を定義します。クラスはメタクラスのインスタンスです。

あなたが与える例では、何が起こっているのですか:

  1. への呼び出し__new__は、MRO の次のものにバブルアップされています。この場合、;super(MyType, cls)に解決されます。typeを呼び出すとtype.__new__、Python は通常のインスタンス作成手順を完了できます。

  2. この例では、メタクラスを使用してシングルトンを適用しています。彼はメタクラスでオーバーライド__call__しているため、クラス インスタンスが作成されるたびにそれをインターセプトし、インスタンスが既に存在する場合はインスタンスの作成をバイパスできます ( に格納されていますcls.instance)。クラスを作成するときにのみ呼び出されるため、メタクラスでのオーバーライド__new__は十分ではないことに注意してください。ただし、クラスのオーバーライド は機能します。__new__

  3. これは、クラスを動的に作成する方法を示しています。ここでは、提供されたクラスの名前を作成されたクラス名に追加し、それをクラス階層にも追加しています。

どのようなコード例を探しているのか正確にはわかりませんが、メタクラス、継承、およびメソッド解決を示す簡単な例を次に示します。

print('>>> # Defining classes:')

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(metaclass=MyMeta):
    def __init__(self):
        super(A, self).__init__()
        print("A init")

    def meth(self):
        print("A.meth")

class B(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")

print('>>> c_obj = C()')
c_obj = C()
print('>>> c_obj.meth()')
c_obj.meth()
print('>>> C.meta_meth()')
C.meta_meth()
print('>>> c_obj.meta_meth()')
c_obj.meta_meth()

出力例 (Python >= 3.6 を使用):

>>> # Defining classes:
meta: creating A ()
meta: creating B ()
meta: creating C (A, B)
>>> c_obj = C()
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 "metatest.py", line 41, in <module>
    c_obj.meta_meth()
AttributeError: 'C' object has no attribute 'meta_meth'
于 2008-12-28T11:36:08.443 に答える
9

これがより実用的な答えです。

めったに問題にならない

  1. Python のメタクラスとは」. 要するにtype、すべてのクラスのメタクラスです。これを実際に使用することはほとんどありません。

    class X(object):
        pass
    type(X) == type
    
  2. " Python のメタクラスの (具体的な) ユースケースは何ですか? ". 結論。なし。

  3. " Python の Super は気の利いたものですが、使えません". 興味深いメモですが、実用的な価値はほとんどありません。複雑な多重継承ネットワークを解決する必要はありません。多重継承の代わりに明示的な戦略設計を使用することで、この問題の発生を簡単に防ぐことができます。

これは、過去 7 年間の Python プログラミングでの私の経験です。

  1. クラスには、自分のクラスから への単純なチェーンを形成する 1 つ以上のスーパークラスがありobjectます。

  2. 「クラス」の概念は、 という名前のメタクラスによって定義されますtype。「クラス」の概念を拡張したいと思うかもしれませんが、これまでのところ、実際に登場することはありません。一度もありません。 type常に正しいことをします。

  3. を使用superすると、実際には非常にうまく機能します。サブクラスがそのスーパークラスに従うことを可能にします。これらのメタクラスの例にたまたま現れているのは、組み込みのメタクラスを拡張しているためですtype

    ただし、すべてのサブクラスの状況でsuper、スーパークラスを拡張するために使用します。

メタクラス

メタクラスの問題は次のとおりです。

  • すべてのオブジェクトには、その型定義または「クラス」への参照があります。

  • Aclass自体もオブジェクトです。

  • したがって、タイプのオブジェクトには、そのclassタイプまたは「クラス」への参照があります。「クラス」の「クラス」はメタクラスです。

「クラス」は C++ ランタイム オブジェクトではないため、これは C++ では発生しません。Java、Smalltalk、および Python で発生します。

メタクラスは、クラス オブジェクトの動作を定義します。

  • クラスとの対話の 90% は、クラスに新しいオブジェクトの作成を依頼することです。

  • 10% の確率で、クラス メソッドまたはクラス変数 (C++ または Java 用語で「静的」) を使用します。

クラスレベルのメソッドのユースケースをいくつか見つけました。クラス変数のユースケースはほとんどありません。オブジェクトの構築方法を変更する状況に遭遇したことはありません。

于 2008-12-28T14:11:03.110 に答える