Python的元类
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.name 和 Filed.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留言。
代码来自:https://github.com/bslatkin/effectivepython
Python的元类的更多相关文章
- python 通过元类控制类的创建
一.python中如何创建类? 1. 直接定义类 class A: a = 'a' 2. 通过type对象创建 在python中一切都是对象 在上面这张图中,A是我们平常在python中写的类,它可以 ...
- Python 的元类设计起源自哪里?
一个元老级的 Python 核心开发者曾建议我们( 点击阅读),应该广泛学习其它编程语言的优秀特性,从而提升 Python 在相关领域的能力.在关于元编程方面,他的建议是学习 Hy 和 Ruby.但是 ...
- 关于python的元类
当你创建一个类时: class Foo(Bar): pass Python做了如下的操作: Foo中有__metaclass__这个属性吗?如果是,Python会在内存中通过__metaclass__ ...
- 理解python的元类
看了一篇文档,借鉴一下!写下自己对python元类的理解,欢迎各位大神给出意见. 我的理解就是 type用来创建元类,元类用来创建类,类用来创建实例 这样一想,是不是可以认为元类创建类的过程等同于类创 ...
- 【转】Python 之 元类
原文链接: https://stackoverflow.com/questions/100003/what-is-a-metaclass-in-python http://python.jo ...
- Python中元类
元类(metaclass) 简单地说,元类就是一个能创建类的类,而类class 是由type创建的,class可以创建对象 type与object的关系详见:python中type和object 1. ...
- 转---一文读懂 python 的元类
译注:这是一篇在Stack overflow上很热的帖子.提问者自称已经掌握了有关Python OOP编程中的各种概念,但始终觉得元类(metaclass)难以理解.他知道这肯定和自省有关,但仍然觉得 ...
- Python之元类详细解析
一.补充内置函数isinstance和issubclass 1.isinstance是判断一个对象是不是由一个对象产生的 class Foo: pass obj=Foo() print(isinsta ...
- Python之元类详解
一.引子 元类属于Python面向对象编程的深层魔法,99%的人都不得要领,一些自以为搞明白元类的人其实也是自圆其说,点到为止,从队元类的控制上来看就破绽百出,逻辑混乱: 二.什么是元类 一切源自于一 ...
随机推荐
- Python列表(一)
列表由一系列特定顺序排列的元素组成,在python中使用[]来表示列表,并用,来进行元素分割. >>> name_list['alben', 'james', 'harden', ' ...
- MySql学习笔记(五) —— 存储过程
存储过程是MySql 5支持的特性,它是一组为了完成特定功能的SQL语句集,经过编译之后存储在数据库中,当需要使用该组SQL语句时用户只需要通过指定储存过程的名字并给定参数就可以调用执行它了,简而言之 ...
- HDFS运行原理
HDFS(Hadoop Distributed File System )Hadoop分布式文件系统.是根据google发表的论文翻版的.论文为GFS(Google File System)Googl ...
- (数字IC)低功耗设计入门(六)——门级电路低功耗设计优化
三.门级电路低功耗设计优化 (1)门级电路的功耗优化综述 门级电路的功耗优化(Gate Level Power Optimization,简称GLPO)是从已经映射的门级网表开始,对设计进行功耗的优化 ...
- JavaSE教程-02Java基本语法-BUG:易错点
1.区别文档注释和多行注释 多行注释:多一个* 多行注释 格式: /* 注释文字 */ 文档注释 格式:/** 注释文字 */ 2.有关变量名.类名.方法名等注意点 由字母.数字.下划线.$组成,但不 ...
- 从零开始理解JAVA事件处理机制(3)
我们连续写了两小节的教师-学生的例子,必然觉得无聊死了,这样的例子我们就是玩上100遍,还是不知道该怎么写真实的代码.那从本节开始,我们开始往真实代码上面去靠拢. 事件最容易理解的例子是鼠标事件:我们 ...
- mysql too many connections 问题
我的处理步骤: 第一步:首次确定你的服务可不可以重启,如果可以重启转第二步,如果不可以重启转第三步,这个主要考虑已经部署到客户现场或者正在使用中的数据库不能重启. 第二步:查找mysql的安装路径,这 ...
- profiler内存优化:警惕回调函数
最近做profiler内存优化,踩了一个深坑,觉得有必要做一下笔记. 过程是这样的,游戏启动后,会启动更新模块,加载更新界面,更新检测完成后会切换场景进入登陆界面.切换场景会自动释放上一个场景的资源. ...
- linux 系统备份日志
题目: 备份日志 小明是一个服务器管理员,他需要每天备份论坛数据(这里我们用日志替代),备份当天的日志并删除之前的日志.而且备份之后文件名是年-月-日的格式.alternatives.log在/var ...
- Azure 基础:Table storage
Azure Storage 是微软 Azure 云提供的云端存储解决方案,当前支持的存储类型有 Blob.Queue.File 和 Table.其中的 Table 就是本文的主角 Azure Tabl ...