• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

详细讲解Python中的元类及其用法

python 搞代码 4年前 (2022-01-09) 47次浏览 已收录 0个评论

1、用元类验证子类

每当我们定义新类的时候,元类就会运行雅正代码,以确保这个新类符合规定的规范。
Python系统把子类的class语句处理完毕,就会调用元类的 __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) * 180class Triangle(Polygon):    sides = 3print(Triangle.interior_angles())

2、用元类注册子类

每次从基类中继承子类时,基类的元类都可以自动运行注册代码。
这在需要反向查找 ‘reverse lookup’ 时很有用,使得在简单标识符和对应的类之间,建立映射关系。
依然利用的是class语句执行完,自动调用元类的 __new__ 方法。

import json registry = {}def register_class(target_class):    registry[target_class.__name__] = target_classdef 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 clsclass 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):    passclass Vector3D(RegisteredSerializable):    def __init__(self, x, y, z):        super().__init__(x, y, z)        self.x, self.y, self.z = x, y, zv3 = 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

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 clsclass DatabaseRow(object, metaclass=M<strong>本文来源gaodai#ma#com搞@代~码^网+</strong>eta):    passclass 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__)

元类总结就到这里,自己也没有完全理解清楚。
希望对此有深刻理解的pythoner留言。

代码来自:

以上就是详细讲解Python中的元类及其用法的详细内容,更多请关注搞代码gaodaima其它相关文章!


搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:详细讲解Python中的元类及其用法
喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址