写在前面

之前在看廖雪峰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(元类)

  1. 先看下如何定义一个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
  2. 分析上面的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)
  3. 使用上面的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: 类中必须有文档注释
  4. 再测试下文档注释的限制
    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: 类中必须有文档注释
  5. 符合要求的类
    class Persion(metaclass=PersionMetaclass):
    """文档注释"""
    pass Persion()

参悟python元类(又称metaclass)系列实战(一)的更多相关文章

  1. python 元类 type metaclass

    python中一切皆对象,类对象创建实例对象,元类创建类对象,元类创建元类. 元类创建类对象有2中方式: 一.type方法 type(类名, 由父类名称组成的元组(针对继承的情况,可以为空),包含属性 ...

  2. python 元类(metaclass)

    元类参见老师的博客 http://www.cnblogs.com/linhaifeng/articles/8029564.html

  3. python元类:type和metaclass

    python元类:type和metaclass python中一切皆对象,所以类本身也是对象.类有创建对象的能力,那谁来创建类的呢?答案是type. 1.用tpye函数创建一个类 class A(ob ...

  4. 第十三章、元类(metaclass)

    目录 第十三章.元类(metaclass) 一.什么是元类 二.为什么用元类 第十三章.元类(metaclass) 一.什么是元类 在python中一切皆对象,那么我们用class关键字定义的类本身也 ...

  5. 深入理解python元类

    类也是对象 在理解元类之前,你需要先掌握Python中的类.Python 中的类概念借鉴 Smalltalk,这显得有些奇特.在大多数编程语言中,类就是一组用来描述如何生成一个对象的代码段.当然在 P ...

  6. Python 元类 - Metaclasses

    Python 元类 - Metaclasses 默认情况下儿, classes 是有 type() 构造的. 类的结构体在一个新的 namespace 被执行, 类的名字 class name 绑定( ...

  7. Python进阶丨如何创建你的第一个Python元类?

    摘要:通过本文,将深入讨论Python元类,其属性,如何以及何时在Python中使用元类. Python元类设置类的行为和规则.元类有助于修改类的实例,并且相当复杂,是Python编程的高级功能之一. ...

  8. Python 元类详解

    一.Type介绍 在Python中一切皆对象,类它也是对象,而元类其实就是用来创建类的对象(由于一切皆对象,所以元类其实也是一个对象). 先来看这几个例子: 例1: In [1]: type(12) ...

  9. python 元类metaclass

    文章转自:http://www.cnblogs.com/linhaifeng/articles/8029564.html 一 知识储备 exec:三个参数 参数一:字符串形式的命令 参数二:全局作用域 ...

随机推荐

  1. Python练习题 049:Project Euler 022:姓名分值

    本题来自 Project Euler 第22题:https://projecteuler.net/problem=22 ''' Project Euler: Problem 22: Names sco ...

  2. RT Thread SPI设备 使用

    后记: 之前,我把SPI的片选在Cubemx中配置成了SPI_NSS.现在我给它改为了GPIO_OUTPUT.  同时参考了别人的类似的一个操作无线模块(采用SPI设备驱动)的例子程序(清楚了RTT的 ...

  3. matlab中drawnow更新图窗并处理回调

    来源:https://ww2.mathworks.cn/help/matlab/ref/drawnow.html?searchHighlight=drawnow&s_tid=doc_srcht ...

  4. 【题解】CF940F Machine Learning

    Link 题目大意:单点修改,每次询问一个区间的所有颜色出现次数的\(\text{Mex}.\) 例如,区间中三种颜色分别出现了\(2,2,3\)次,又因为其他颜色出现次数一定是\(0\),所以这里的 ...

  5. Ztree树节点应用

    树节点增删改查: 前台jsp页面: <% String root=request.getContextPath();//获取项目目录 %> <SCRIPT type="te ...

  6. Request对象基础应用实例代码一

    输入用户名:<br><input type="text" name="yhm"><br><br>输入密码:< ...

  7. 如何修改或新增visual studio 的模板

    在 visual studio 中添加模板,我这里是新增mvc.net的模板 vs2017在文件夹=>(举例说明,请替换为相应的安装目录) D:\Program Files (x86)\Micr ...

  8. BUUCTF-数据包中的线索 1

    打开题目里面一个pcapng的文件,于是我们拖进wireshark流量分析一波 发现有http的流量,于是我们过滤http 让后追踪http,然后发现base64的编码, 于是我们看到了base64编 ...

  9. 如果你想or即将成为一名程序员,那你需要知道这些东西!上岗须知~

    前两天公司学院的同学给我看了一下即将入职的应届生的数量,真是不少.感慨一下,一批新人即将到来,而自己又老去了一岁.码农是一个必将终身学习的职业.而相关的知识越来越多了.接下来该学什么?接下来该干什么? ...

  10. 【暑假集训】HZOI2019 水站 多种解法

    题目内容 已知有一个\(n\)层的水站: \(W_i\)表示未操作之前第\(i\)层的已有水量: \(L_i\)表示第\(i\)个水站能够维持或者储存的水的重量: 表示在第\(P_i\)层进行减压放水 ...