参悟python元类(又称metaclass)系列实战(一)
写在前面
之前在看廖雪峰python系列的教程时,对元类的章节一直头大,总在思考我到底适不适合学习python,咋这么难,尤其是ORM的部分,倍受打击;后来从0到1手撸了一套ORM,才稍微进阶了一点理解。
这个系列会从元类开始梳理,最后按廖老师的demo撸一个ORM,希望能对大家有所增益。
本文中提及的“模板”,泛指“类(class)”。
有误的地方恳请大神指正下。
先从普通类实例化的过程探究下
class Persion:
def __init__(self, name):
self.name = name
# 把它实例化
p1 = Persion()
print(type(p1)) # <class '__main__.Persion'>
# 打印的信息显示p1这个实例是由 Persion 这个模板创建的,那Persion这个模板是谁创建的?
print(type(Persion)) # <class 'type'>,是type创建了一个叫Persion的模板
# 由此可见,在实例化 p1 了时候,实际上是走了两步,1.用type创建Persion模板; 2.用Persion模板创建实例p1
思考1:对于过程1,是否就意味着可以用type代替class去创建Persion模板?
def fn(self, name):
self.name = name
# type 接收3个位置参数,1.名字:Str,2.父类们: tuple,3.绑定的属性(方法):dict
Persion = type('demo', (object,), dict(__init__=fn))
# 等同于前面通过class声明的写法
思考2:如果能自定义type的子类并用其创建Persion模板,就意味着可以定制创建过程,这种type的子类,就叫做metaclass(元类)
- 先看下如何定义一个type的子类
# 按照默认习惯,metaclass的类名总是以Metaclass结尾,以便清楚地表示这是一个metaclass
class PersionMetaclass(type):
# 重写父类type中的new方法
def __new__(cls, name: str, bases: tuple, attrs: dict):
"""
类似class中的__init__方法,实例化时被调用
@cls: 类似__init__中的self,代表自己,这里代指‘类’自己
@name: 模板的名字
@bases: 父类的集合
@attrs: 属性(方法)集
"""
# 调用type创建class
Persion = type.__new__(cls, name, bases, attrs)
return Persion
- 分析上面的code,不难发现在调type创建class之前,可以加入定制的内容
# 需求:1.类名首字母必须大写,2.类中必须有文档注释
class PersionMetaclass(type):
def __new__(cls, name, bases, attrs): if not name.istitle():
raise TypeError('类名首字母必须大写') cls.doc = attrs.get('__doc__')
if cls.doc is None or len(cls.doc.strip()) == 0:
raise TypeError('类中必须有文档注释') return type.__new__(cls, name, bases, attrs)
- 使用上面的metaclass测试一下类名首字母大写的限制
# 定义类的时候,需要显示的指出用 PersionMetaclass 来定制类,关键字“metaclass” class persion(metaclass=PersionMetaclass):
pass persion()
Traceback (most recent call last):
File "testmetaclass.py", line 39, in <module>
class Persion(metaclass=PersionMetaclass):
File "testmetaclass.py", line 35, in __new__
raise TypeError('类中必须有文档注释')
TypeError: 类中必须有文档注释
- 再测试下文档注释的限制
class Persion(metaclass=PersionMetaclass):
pass Persion()
Traceback (most recent call last):
File "testmetaclass.py", line 39, in <module>
class Persion(metaclass=PersionMetaclass):
File "testmetaclass.py", line 35, in __new__
raise TypeError('类中必须有文档注释')
TypeError: 类中必须有文档注释
- 符合要求的类
class Persion(metaclass=PersionMetaclass):
"""文档注释"""
pass Persion()
参悟python元类(又称metaclass)系列实战(一)的更多相关文章
- python 元类 type metaclass
python中一切皆对象,类对象创建实例对象,元类创建类对象,元类创建元类. 元类创建类对象有2中方式: 一.type方法 type(类名, 由父类名称组成的元组(针对继承的情况,可以为空),包含属性 ...
- python 元类(metaclass)
元类参见老师的博客 http://www.cnblogs.com/linhaifeng/articles/8029564.html
- python元类:type和metaclass
python元类:type和metaclass python中一切皆对象,所以类本身也是对象.类有创建对象的能力,那谁来创建类的呢?答案是type. 1.用tpye函数创建一个类 class A(ob ...
- 第十三章、元类(metaclass)
目录 第十三章.元类(metaclass) 一.什么是元类 二.为什么用元类 第十三章.元类(metaclass) 一.什么是元类 在python中一切皆对象,那么我们用class关键字定义的类本身也 ...
- 深入理解python元类
类也是对象 在理解元类之前,你需要先掌握Python中的类.Python 中的类概念借鉴 Smalltalk,这显得有些奇特.在大多数编程语言中,类就是一组用来描述如何生成一个对象的代码段.当然在 P ...
- Python 元类 - Metaclasses
Python 元类 - Metaclasses 默认情况下儿, classes 是有 type() 构造的. 类的结构体在一个新的 namespace 被执行, 类的名字 class name 绑定( ...
- Python进阶丨如何创建你的第一个Python元类?
摘要:通过本文,将深入讨论Python元类,其属性,如何以及何时在Python中使用元类. Python元类设置类的行为和规则.元类有助于修改类的实例,并且相当复杂,是Python编程的高级功能之一. ...
- Python 元类详解
一.Type介绍 在Python中一切皆对象,类它也是对象,而元类其实就是用来创建类的对象(由于一切皆对象,所以元类其实也是一个对象). 先来看这几个例子: 例1: In [1]: type(12) ...
- python 元类metaclass
文章转自:http://www.cnblogs.com/linhaifeng/articles/8029564.html 一 知识储备 exec:三个参数 参数一:字符串形式的命令 参数二:全局作用域 ...
随机推荐
- SpringBoot-03-JSR303数据校验和多环境切换
3.3 JSR303数据校验 先看如何使用 Springboot中可以用@Validated来校验数据,如果数据异常则统一抛出异常,方便异常中心统一处理. 这里我们写个注解让name只支持Em ...
- Go-missing return at end of function
where? Go程序中函数在执行的时候 why? 函数有返回参数,但是函数没有return关键字,报错 way? 添加return返回函数需要返回的参数
- Python练习题 048:Project Euler 021:10000以内所有亲和数之和
本题来自 Project Euler 第21题:https://projecteuler.net/problem=21 ''' Project Euler: Problem 21: Amicable ...
- STM32CubeMX HAL库串口: 使用DMA数据发送、使用DMA不定长度数据接收
转载自 https://blog.csdn.net/euxnijuoh/article/details/81638676
- 上部:问道 | R语言数据分析(北京邮电大学)自整理笔记
第1章 气象万千 数以等观 数据分析:发现数据背后的规律 等号的重要性,建立模型 第2章所谓学习.归类而已 2.1所谓学习,归类而已(1) ps:机器学习只是归归类? 有监督学习--分类:无监督学习- ...
- 这个网易云JS解密,老网抑云看了都直呼内行
最近更新频率慢了,这不是因为CK3发售了嘛,一个字就是"肝".今天来看一下网易云音乐两个加密参数params和encSecKey,顺便抓取一波某歌单的粉丝,有入库哦,使用mysql ...
- Oracle 和 MySQL 在显示数据库名和表名的区别
Oracle 显示数据库名和表名 Oracle 查看表名: select table_name from user_tables; select table_name from dba_tables; ...
- Windows7 提示“无法访问您可能没有权限使用网络资源”的解决办法
大家经常会碰到,电脑A(Windows7)访问局域网打印机的时候出现提示"无法访问你可能没有权限使用网络资源",导致无法正常使用打印机. 那么出现这种情况该如何解决呢? 解决方法: ...
- Docker笔记6:Docker 常见命令及镜像管理
目 录 一.Docker 常用命令 docker version 命令 docker info 命令 二.Docker 镜像管理 搜索镜像:docker search 镜像名 获取镜像:docker ...
- C#使用RabbitMq队列(Sample,Work,Fanout,Direct等模式的简单使用)
1:RabbitMQ是个啥?(专业术语参考自网络) RabbitMQ是实现了高级消息队列协议(AMQP)的开源消息代理软件(亦称面向消息的中间件). RabbitMQ服务器是用Erlang语言编写的, ...