> 백엔드 개발 > 파이썬 튜토리얼 > 메타클래스와 Python에서의 사용법에 대한 자세한 설명

메타클래스와 Python에서의 사용법에 대한 자세한 설명

巴扎黑
풀어 주다: 2017-07-20 09:30:33
원래의
1567명이 탐색했습니다.

1. 메타클래스를 사용하여 하위 클래스 확인

새 클래스를 정의할 때마다 메타클래스는 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())
로그인 후 복사

2、用元类注册子类

每次从基类中继承子类时,基类的元类都可以自动运行注册代码。
这在需要反向查找 ‘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)
로그인 후 복사

3、用元类注解类的属性

使用元类像是在 class 语句上放置了挂钩,class语句处理完毕,挂钩就会立刻触发。
下列中借助元类设置了 Filed.nameFiled.name이렇게 하면 이 클래스의 __init__ 메서드에 확인 코드를 넣고 확인하기 전에 개체가 빌드될 때까지 기다릴 필요가 없습니다.


다음 예에서는 모서리가 3개 미만인 하위 클래스가 정의됩니다. 클래스 문이 끝나면 메타클래스 확인 코드가 클래스를 거부합니다.

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__)
로그인 후 복사

2. 메타클래스로 하위 클래스 등록

기본 클래스에서 하위 클래스를 상속받을 때마다 기본 클래스의 메타클래스가 자동으로 등록 코드를 실행할 수 있습니다.

이는 단순 식별자와 해당 클래스 간의 매핑을 설정하기 위해 '역조회'가 필요할 때 유용합니다. 🎜아직도 사용되는 것은 class 문이 실행된 후 메타클래스의 __new__ 메서드가 자동으로 호출된다는 것입니다. 🎜rrreee🎜3. 클래스 속성에 주석을 달기 위해 메타클래스를 사용하세요🎜🎜메타클래스를 사용하는 것은 클래스 문이 처리된 후 후크가 즉시 실행되는 것과 같습니다. 🎜다음에서는 Filed.nameFiled.name이 메타클래스의 도움으로 설정됩니다. 🎜rrreee🎜🎜메타클래스 요약은 여기서 끝나는데, 완전히 이해가 안 되네요. 🎜이에 대해 깊이 이해하고 있는 파이썬러 분들이 메시지를 남겨주시면 좋겠습니다. 🎜🎜코드 출처: 🎜

위 내용은 메타클래스와 Python에서의 사용법에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿