最新文章专题视频专题问答1问答10问答100问答1000问答2000关键字专题1关键字专题50关键字专题500关键字专题1500TAG最新视频文章推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37视频文章20视频文章30视频文章40视频文章50视频文章60 视频文章70视频文章80视频文章90视频文章100视频文章120视频文章140 视频2关键字专题关键字专题tag2tag3文章专题文章专题2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章专题3
当前位置: 首页 - 科技 - 知识百科 - 正文

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

来源:动视网 责编:小采 时间:2020-11-27 14:23:32
文档

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

详细讲解Python中的元类及其用法:1、用元类验证子类每当我们定义新类的时候,元类就会运行雅正代码,以确保这个新类符合规定的规范。Python系统把子类的class语句处理完毕,就会调用元类的 __new__ 方法。元类可以通过 __new__ 方法,获取子类、孙子类的名称,父亲及属性。这样使得我们不需要
推荐度:
导读详细讲解Python中的元类及其用法:1、用元类验证子类每当我们定义新类的时候,元类就会运行雅正代码,以确保这个新类符合规定的规范。Python系统把子类的class语句处理完毕,就会调用元类的 __new__ 方法。元类可以通过 __new__ 方法,获取子类、孙子类的名称,父亲及属性。这样使得我们不需要


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) * 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

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__)

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

代码来自:

文档

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

详细讲解Python中的元类及其用法:1、用元类验证子类每当我们定义新类的时候,元类就会运行雅正代码,以确保这个新类符合规定的规范。Python系统把子类的class语句处理完毕,就会调用元类的 __new__ 方法。元类可以通过 __new__ 方法,获取子类、孙子类的名称,父亲及属性。这样使得我们不需要
推荐度:
标签: 用法 python 类的
  • 热门焦点

最新推荐

猜你喜欢

热门推荐

专题
Top