6

私はこれを経験しました:Pythonのメタクラスとは何ですか?

しかし、いつメタクラスの概念を使用する必要があり、いつ非常に便利なのか、より具体的に説明できる人はいますか?

以下のようなクラスがあるとします。

 class Book(object):
    CATEGORIES = ['programming','literature','physics']
    def _get_book_name(self,book):
        return book['title']
    def _get_category(self, book):
        for cat in self.CATEGORIES:
            if book['title'].find(cat) > -1:
                return cat  
        return "Other"


if __name__ == '__main__':
    b = Book()
    dummy_book = {'title':'Python Guide of Programming', 'status':'available'}
    print b._get_category(dummy_book)

このクラスの場合。

メタ クラスを使用する必要があるのはどのような場合ですか? また、それが役立つのはなぜですか?

前もって感謝します。

4

5 に答える 5

9

作成中にクラスを変更する場合は、メタクラスを使用します。メタクラスが必要になることはほとんどなく、デバッグが難しく、理解するのも困難ですが、フレームワークを使いやすくする場合もあります。私たちの 600Kloc コード ベースでは、メタクラスを 7 回使用しました。1 回は ABCMeta、4 回は Django の models.SubfieldBase、2 回は Django でクラスをビューとして使用できるようにするメタクラスです。@Ignacio が書いているように、メタクラスが必要であることを知らない場合(そして他のすべてのオプションを検討した場合)、メタクラスは必要ありません

于 2012-04-28T07:10:05.613 に答える
4

概念的には、クラスは一連のオブジェクト (クラスのインスタンス) に共通するものを定義するために存在します。それで全部です。クラスによって定義された共有パターンに従って、クラスのインスタンスについて考えることができます。すべてのオブジェクトが異なる場合、わざわざクラスを使用するのではなく、辞書を使用するだけです。

メタクラスは通常のクラスであり、同じ理由で存在します。そのインスタンスに共通するものを定義します。デフォルトのメタクラスtypeは、クラスとインスタンスを慣れ親しんだ方法で動作させる通常のルールをすべて提供します。

  • インスタンスの属性検索では、インスタンス、そのクラス、すべてのスーパークラスが MRO 順にチェックされます。
  • MyClass(*args, **kwargs)invokesを呼び出しi = MyClass.__new__(MyClass, *args, **kwargs)てインスタンスを取得してから、invokesi.__init__(*args, **kwargs)を呼び出して初期化します
  • クラスは、クラス ブロックでバインドされたすべての名前をクラスの属性にすることによって、クラス ブロック内の定義から作成されます。

通常のクラスとは異なる動作をするいくつかのクラスが必要な場合は、メタクラスを定義して、通常とは異なるクラスをtype. おそらく、異なる種類のクラスを完全typeに異なるものにしたくないので、メタクラスはほぼ確実に のサブクラスになります。ブックのサブセットの動作を少し変えて (たとえば、他の作品の編集物であるブック) 、完全に異なるクラスではなく のサブクラスを使用したい場合と同様です。Book

一部のクラスを通常のクラスとは異なる方法で動作させる方法を定義しようとしていない場合、メタクラスはおそらく最適なソリューションではありません。「インスタンスがどのように機能するかをクラスが定義する」ことは、すでに非常に柔軟で抽象的なパラダイムであることに注意してください。ほとんどの場合、クラスの動作を変更する必要はありません。

グーグルで検索すると、クラスの作成に関連する多くのことを実行するために実際に使用されているメタクラスの例がたくさん表示されます。多くの場合、クラス属性を自動的に処理したり、どこかから自動的に新しいものを見つけたりします。メタクラスの優れた使用法とは言えません。クラスの動作を変更しているのではなく、一部のクラスを処理しているだけです。私の意見では、クラスを作成するためのファクトリ関数、またはクラスの作成直後に呼び出すクラス メソッド、または何よりもクラス デコレータは、この種のものを実装するためのより良い方法です。

しかし、Python のクラスの既定の動作を概念的に単純なものにするために、複雑なコードを記述していることに気付くことがあります。実際には、「さらに踏み込んで」それをメタクラス レベルで実装するのに役立ちます。

かなり些細な例は「シングルトン パターン」です。ここでは、インスタンスが 1 つしか存在できないクラスがあります。クラスを呼び出すと、インスタンスが既に作成されている場合は既存のインスタンスが返されます。個人的に私はシングルトンに反対であり、その使用についてはアドバイスしません (それらはグローバル変数であり、微妙なバグを引き起こす可能性をさらに高めるために、新しく作成されたインスタンスのように巧妙に偽装されていると思います)。しかし、人々はそれらを使用しており、 と を使用してシングルトン クラスを作成するための膨大な数のレシピが__new__あり__init__ます。このようにすると、少しイライラすることがあります。これは主に、Python が呼び出してから呼び出したいためです__new____init__その結果、誰かがシングルトンへのアクセスを要求するたびに初期化コードを再実行しない方法を見つける必要があります。しかし、クラスを呼び出したときに何をしたいのかを Python に直接伝えることができれば、Python がやりたいことを設定して最終的にやりたいことをやらせるよりも簡単ではないでしょうか?

class Singleton(type):
    def __init__(self, *args, **kwargs):
        super(Singleton, self).__init__(*args, **kwargs)
        self.__instance = None

    def __call__(self, *args, **kwargs):
        if self.__instance is None:
            self.__instance = super(Singleton, self).__call__(*args, **kwargs)
        return self.__instance

10 行未満で、 を追加するだけで通常のクラスをシングルトンに変換します__metaclass__ = Singleton。つまり、シングルトンであることを宣言するだけです。クラスレベルで何かを直接ハッキングするよりも、このレベルでこの種のものを実装する方が簡単です。

しかし、あなたの特定Bookのクラスについては、メタクラスによって助けられる何かをする必要はないようです。クラスがどのように機能するかの通常のルールが、単純な方法で単純であるべきことを行うことを妨げていることが判明しない限り、実際にメタクラスに到達する必要はありませんこれらすべてのクラスに多くのタイプを入力する必要があるため、共通ビットを自動生成できないだろうか?")。実際、仕事で毎日 Python を使用しているにもかかわらず、実際にメタクラスを実際に使用したことはありません。私のメタクラスはすべて、上記のようなおもちゃの例であるSingletonか、ばかげた探索です。

于 2012-04-28T09:15:48.837 に答える
4

クラスの作成など、クラスのデフォルトの動作をオーバーライドする必要がある場合は常に、メタクラスが使用されます。

クラスは、名前、ベースのタプル、およびクラスdictから作成されます。作成プロセスを傍受して、これらの入力のいずれかに変更を加えることができます。

クラスが提供するサービスをオーバーライドすることもできます。

  • インスタンスの作成に使用される __call__
  • クラスの属性とメソッドを検索するために使用される __getattribute__
  • 設定属性を制御する __setattr__
  • クラスの表示方法を制御する __repr__

要約すると、メタクラスは、クラスの作成方法を制御する必要がある場合、またはクラスによって提供されるサービスを変更する必要がある場合に使用されます。

于 2012-04-28T09:54:48.940 に答える
1

Class[x]何らかの理由でなどを実行したい場合x in Classは、メタクラスを使用する必要があります。

class Meta(type):
    def __getitem__(cls, x):
        return x ** 2

    def __contains__(cls, x):
        return int(x ** (0.5)) == x ** 0.5

# Python 2.x
class Class(object):
    __metaclass__ = Meta

# Python 3.x
class Class(metaclass=Meta):
    pass

print Class[2]
print 4 in Class
于 2012-04-28T07:33:21.890 に答える
-1

いつどのようにメタ クラスを使用するかを知るには、 Meta Class Made Easyのリンクを確認してください。

于 2012-04-28T10:24:26.430 に答える