ホームページ >バックエンド開発 >Python チュートリアル >Python クラスとメタクラスの詳細 II
1 レベル戻って、クラス オブジェクト自体がどのように生成されるかを見てみましょう。
type() メソッドがオブジェクトの型をチェックしたり、オブジェクトがどのクラスから生成されたかを判断できることはわかっています:
print(type(12)) print(type('python'))
<class 'int'> <class 'str'>
class A: passprint(type(A))
<class 'type'>
このコードから、クラス オブジェクト A が type() によって生成されていることがわかります。つまり、type は新しいオブジェクトの生成にも使用でき、生成されるのはクラス オブジェクトであるため、すべてのクラス オブジェクトのクラスになります:
print(type.__doc__)
type(object_or_name, bases, dict) type(object) -> the object's type type(name, bases, dict) -> a new type
class クラスを定義するための構文は、実際には type に変換されます。 (name,bases, dict)、ここで、name パラメーターはクラスの名前、bases は親クラスを継承するタプル、dict はクラスの属性とメソッドです:
class A: pass# 实际上等于B = type('A', (), {}) print(A.__name__ == B.__name__)
True
理論的には、これは次の意味です。メタクラスですが、実用的な観点からは、クラス構文を使用する方が明らかに便利です。メタクラスの実際の意味は、型クラスを継承して新しいメタクラスを構築し、特定の操作を実行して特定のクラス オブジェクトを生成することです。行動。この観点から見ると、型クラスを継承することを除いて、その本質は通常のクラス オブジェクトと変わりません。
インスタンスを生成するとき、__init__ メソッドを呼び出すことによって初期化されます。実際には、__new__ メソッドが最初に呼び出されてインスタンスを作成し、次に __init__ によって初期化されます。これは、__new__ が変数の宣言を担当し、__init__ が担当するようなものです。変数の宣言の場合は初期化と同じです。ここには、__new__(cls,) の戻り値は cls パラメーターのインスタンスでなければならないというルールがあります。そうでない場合、たとえば enum.Enum の定義では、列挙型がシングルトン モードであるため、__init__ がトリガーされません。したがって、__new__ の定義では、そのインスタンスが返されない場合、初期化されません:
class Enum: def __new__(cls, value): print(cls, value) return value def __init__(self): print("Will not be called!") e = Enum(1)
<class '__main__.Enum'> 1
通常、__new__ を自分で定義するときは、親クラスの __new__ メソッドを呼び出して cls のインスタンスを作成する必要があります。メタクラスを定義するには、上記の type の使用法を呼び出します (メタクラスは type を継承するため):
class MetaEnum(type): def __new__(metaclass, name, base, attrs): print("Metaclass: {}\nName: {}\nParents: {}\nAttributes: {}".format(metaclass, name, base, attrs)) return super().__new__(metaclass, name, base, attrs)
class Enum(metaclass=MetaEnum): # Python 2.7 中定义元类的方法是使用 __metaclass__ 变量 # [PEP 3115](https://www.python.org/dev/peps/pep-3115/) # 将 Python 3.0 以后语法改为 class Cls(metaclass=Meta) test = 0
Metaclass: <class '__main__.MetaEnum'> Name: Enum Parents: () Attributes: {'__qualname__': 'Enum', '__module__': '__main__', 'test': 0}
今度は、Enum のクラスを見てみましょう。これはもはや type ではなく、そのメタクラス MetaEnum:
type( Enum)
__main__.MetaEnum
Except __new__ メソッドに加えて、PEP 3115 は、初期化された名前空間 (つまり、型の 3 番目のパラメーター) を設定するために使用される __prepare__ 属性も定義します。たとえば、列挙型の属性名の繰り返しを制限する必要があります。これを使用すると、メタクラスを通じてクラスの動作を制限できます
Python のすべてのオブジェクトは、特定のオブジェクトのインスタンスです。クラスまたは特定のメタクラスのインスタンスです。type は独自のメタクラスと独自のインスタンスです。その背後にある原則は、Python オブジェクト指向プログラミングを理解する上で非常に重要であり、クラスに大幅な変更を加える必要がある場合には、少なくともどこから始めるべきかを知っておくとアイデアが役立ちます。