새 클래스를 정의할 때마다 메타클래스는 Yazheng 코드를 실행하여 새 클래스가 지정된 사양을 충족하는지 확인합니다.
Python 시스템은 하위 클래스의 클래스 문 처리를 마친 후 메타클래스의 __new__
메서드를 호출합니다. 메타클래스는 __new__
메서드를 통해 하위 클래스와 손자 클래스의 이름, 부모 및 속성을 얻을 수 있습니다. __new__
方法。元类可以通过 __new__
方法,获取子类、孙子类的名称,父亲及属性。
这样使得我们不需要将验证代码放在本类 __init__
方法中,等到构建对象再验证。
下例中,定义一个边数小于3的子类,class语句一结束,元类的验证代码就会拒绝这个class。
class ValidatePolygon(type): def __new__(meta, name, bases, class_dict): # Don't validate the abstract Polygon class if bases != (object,): if class_dict['sides'] < 3: raise ValueError('Polygons need 3+ sides') return type.__new__(meta, name, bases, class_dict) class Polygon(object, metaclass=ValidatePolygon): sides = None # Specified by subclasses @classmethod def interior_angles(cls): return (cls.sides - 2) * 180 class Triangle(Polygon): sides = 3 print(Triangle.interior_angles())
每次从基类中继承子类时,基类的元类都可以自动运行注册代码。
这在需要反向查找 ‘reverse lookup’ 时很有用,使得在简单标识符和对应的类之间,建立映射关系。
依然利用的是class语句执行完,自动调用元类的 __new__
方法。
import json registry = {} def register_class(target_class): registry[target_class.__name__] = target_class def deserialize(data): params = json.loads(data) name = params['class'] target_class = registry[name] return target_class(*params['args']) class Meta(type): def __new__(meta, name, bases, class_dict): cls = type.__new__(meta, name, bases, class_dict) register_class(cls) return cls class Serializable(object): def __init__(self, *args): self.args = args def serialize(self): return json.dumps({ 'class': self.__class__.__name__, 'args': self.args, }) def __repr__(self): return '%s(%s)' % ( self.__class__.__name__, ', '.join(str(x) for x in self.args)) class RegisteredSerializable(Serializable, metaclass=Meta): pass class Vector3D(RegisteredSerializable): def __init__(self, x, y, z): super().__init__(x, y, z) self.x, self.y, self.z = x, y, z v3 = Vector3D(10, -7, 3) print('Before: ', v3) data = v3.serialize() print('Serialized:', data) print('After: ', deserialize(data)) print(registry)
使用元类像是在 class 语句上放置了挂钩,class语句处理完毕,挂钩就会立刻触发。
下列中借助元类设置了 Filed.name
和 Filed.name
이렇게 하면 이 클래스의 __init__
메서드에 확인 코드를 넣고 확인하기 전에 개체가 빌드될 때까지 기다릴 필요가 없습니다.
class Field(object): def __init__(self): # These will be assigned by the metaclass. self.name = None self.internal_name = None def __get__(self, instance, instance_type): if instance is None: return self return getattr(instance, self.internal_name, '') def __set__(self, instance, value): setattr(instance, self.internal_name, value) class Meta(type): def __new__(meta, name, bases, class_dict): for key, value in class_dict.items(): if isinstance(value, Field): value.name = key value.internal_name = '_' + key cls = type.__new__(meta, name, bases, class_dict) return cls class DatabaseRow(object, metaclass=Meta): pass class BetterCustomer(DatabaseRow): first_name = Field() last_name = Field() prefix = Field() suffix = Field() foo = BetterCustomer() print('Before:', repr(foo.first_name), foo.__dict__) foo.first_name = 'Euler' print('After: ', repr(foo.first_name), foo.__dict__)
기본 클래스에서 하위 클래스를 상속받을 때마다 기본 클래스의 메타클래스가 자동으로 등록 코드를 실행할 수 있습니다.
이는 단순 식별자와 해당 클래스 간의 매핑을 설정하기 위해 '역조회'가 필요할 때 유용합니다. 🎜아직도 사용되는 것은 class 문이 실행된 후 메타클래스의__new__
메서드가 자동으로 호출된다는 것입니다. 🎜rrreee🎜3. 클래스 속성에 주석을 달기 위해 메타클래스를 사용하세요🎜🎜메타클래스를 사용하는 것은 클래스 문이 처리된 후 후크가 즉시 실행되는 것과 같습니다. 🎜다음에서는 Filed.name
및 Filed.name
이 메타클래스의 도움으로 설정됩니다. 🎜rrreee🎜🎜메타클래스 요약은 여기서 끝나는데, 완전히 이해가 안 되네요. 🎜이에 대해 깊이 이해하고 있는 파이썬러 분들이 메시지를 남겨주시면 좋겠습니다. 🎜🎜코드 출처: 🎜위 내용은 메타클래스와 Python에서의 사용법에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!