说实话,我真心不太想总结这个东西,算了,炒一下egon的吧

1 引子

1 class Foo:
2 pass
3
4 f1=Foo() #f1是通过Foo类实例化的对象

python中一切皆是对象,类本身也是一个对象,当使用关键字class的时候,python解释器在加载class的时候就会创建一个对象(这里的对象指的是类而非类的实例)

上例可以看出f1是由Foo这个类产生的对象,而Foo本身也是对象,那它又是由哪个类产生的呢?

1 #type函数可以查看类型,也可以用来查看对象的类,二者是一样的
2 print(type(f1)) # 输出:<class '__main__.Foo'> 表示,obj 对象由Foo类创建
3 print(type(Foo)) # 输出:<type 'type'>

2 什么是元类?

元类是类的类,是类的模板

元类是用来控制如何创建类的,正如类是创建对象的模板一样

元类的实例为类,正如类的实例为对象(f1对象是Foo类的一个实例Foo类是 type 类的一个实例)

type是python的一个内建元类,用来直接控制生成类,python中任何class定义的类其实都是type类实例化的对象

3 创建类的两种方式

方式一:

1 class Foo:
2 def func(self):
3 print('from func')

方式二:

1 def func(self):
2 print('from func')
3 x=1
4 Foo=type('Foo',(object,),{'func':func,'x':1})

4 一个类没有声明自己的元类,默认他的元类就是type,除了使用元类type,用户也可以通过继承type来自定义元类(顺便我们也可以瞅一瞅元类如何控制类的创建,工作流程是什么)

 自定制元类
 自定制元类纯净版
 自定制元类精简版
 1 #元类总结
2 class Mymeta(type):
3 def __init__(self,name,bases,dic):
4 print('===>Mymeta.__init__')
5
6
7 def __new__(cls, *args, **kwargs):
8 print('===>Mymeta.__new__')
9 return type.__new__(cls,*args,**kwargs)
10
11 def __call__(self, *args, **kwargs):
12 print('aaa')
13 obj=self.__new__(self)
14 self.__init__(self,*args,**kwargs)
15 return obj
16
17 class Foo(object,metaclass=Mymeta):
18 def __init__(self,name):
19 self.name=name
20 def __new__(cls, *args, **kwargs):
21 return object.__new__(cls)
22
23 '''
24 需要记住一点:名字加括号的本质(即,任何name()的形式),都是先找到name的爹,然后执行:爹.__call__
25
26 而爹.__call__一般做两件事:
27 1.调用name.__new__方法并返回一个对象
28 2.进而调用name.__init__方法对儿子name进行初始化
29 '''
30
31 '''
32 class 定义Foo,并指定元类为Mymeta,这就相当于要用Mymeta创建一个新的对象Foo,于是相当于执行
33 Foo=Mymeta('foo',(...),{...})
34 因此我们可以看到,只定义class就会有如下执行效果
35 ===>Mymeta.__new__
36 ===>Mymeta.__init__
37 实际上class Foo(metaclass=Mymeta)是触发了Foo=Mymeta('Foo',(...),{...})操作,
38 遇到了名字加括号的形式,即Mymeta(...),于是就去找Mymeta的爹type,然后执行type.__call__(...)方法
39 于是触发Mymeta.__new__方法得到一个具体的对象,然后触发Mymeta.__init__方法对对象进行初始化
40 '''
41
42 '''
43 obj=Foo('egon')
44 的原理同上
45 '''
46
47 '''
48 总结:元类的难点在于执行顺序很绕,其实我们只需要记住两点就可以了
49 1.谁后面跟括号,就从谁的爹中找__call__方法执行
50 type->Mymeta->Foo->obj
51 Mymeta()触发type.__call__
52 Foo()触发Mymeta.__call__
53 obj()触发Foo.__call__
54 2.__call__内按先后顺序依次调用儿子的__new__和__init__方法
55 '''

python概念-其实只要简单了解一下,但是却讲了将近两个小时的知识点:元类的更多相关文章

  1. 神级程序员通过两句话带你完全掌握Python最难知识点——元类!

    千万不要被所谓"元类是99%的python程序员不会用到的特性"这类的说辞吓住.因为 每个中国人,都是天生的元类使用者 学懂元类,你只需要知道两句话: 道生一,一生二,二生三,三生 ...

  2. python 内置函数的补充 isinstance,issubclass, hasattr ,getattr, setattr, delattr,str,del 用法,以及元类

    isinstance   是 python中的内置函数 , isinstance()用来判断一个函数是不是一个类型 issubclass  是python 中的内置函数,  用来一个类A是不是另外一个 ...

  3. 两句话掌握python最难知识点——元类

    千万不要被所谓“元类是99%的python程序员不会用到的特性”这类的说辞吓住.因为每个中国人,都是天生的元类使用者 学懂元类,你只需要知道两句话: 道生一,一生二,二生三,三生万物 我是谁?我从哪来 ...

  4. 两句话掌握 Python 最难知识点——元类

    千万不要被所谓“元类是99%的python程序员不会用到的特性”这类的说辞吓住.因为每个中国人,都是天生的元类使用者 学懂元类,你只需要知道两句话: 道生一,一生二,二生三,三生万物 我是谁?我从哪来 ...

  5. Python中对象、类型、元类之间的关系

    Python里的对象.类型和元类的关系很微妙也很有意思. 1989年圣诞节期间,上帝很无聊,于是创造了一个世界. 对象 在这个世界的运转有几条定律. 1.一切都是对象 对象(object)是这个世界的 ...

  6. Python与C的简单比较(Python3.0)

    Python可以说是目前最火的语言之一了,人工智能的兴起让Python一夜之间变得家喻户晓,Python号称目前最最简单易学的语言,现在有不少高校开始将Python作为大一新生的入门语言.本萌新也刚开 ...

  7. 零基础python之列表的简单介绍

    你点击关注,就分你小鱼干 一.概念:列表,由一系列按特定顺序排列的元素组成. 在 python 中,用 [ ] 方括号来表示列表,并用逗号来分割其中的元素. 二.访问列表因素 列表是有序集合,如要访问 ...

  8. Python常用的库简单介绍一下

    Python常用的库简单介绍一下fuzzywuzzy ,字符串模糊匹配. esmre ,正则表达式的加速器. colorama 主要用来给文本添加各种颜色,并且非常简单易用. Prettytable ...

  9. Windows 下针对python脚本做一个简单的进程保护

    前提: 大家运行的脚本程序经常会碰到系统异常关闭.或被其他用户错杀的情况.这样就需要一个进程保护的工具. 本文结合windows 的计划任务,实现一个简单的进程保护的功能. 利用py2exe生产 ex ...

随机推荐

  1. windows 下升级安装mysql8,与旧版本5.6共存

    应开发需求,自mysql5.7开始引入json列类型和相关函数.为了提高数据读写的访问效率因此把数据库从mysql 5.6版升级到最新发行版 mysql 8.0.11 . 特此记录下多版本升级共存的过 ...

  2. [微软官方]SQLSERVER的兼容级别

    ALTER DATABASE (Transact-SQL) 兼容级别 https://docs.microsoft.com/zh-cn/sql/t-sql/statements/alter-datab ...

  3. [转帖].net 4.8 将不再支持win7 win8 版本

    ZT:https://blogs.msdn.microsoft.com/dotnet/2018/07/18/announcing-net-framework-4-8-early-access-buil ...

  4. http和https的优缺点,区别与工作原理

    文章内容 超文本传输协议HTTP协议被用于在Web浏览器和网站服务器之间传递信息,HTTP协议以明文方式发送内容,不提供任何方式的数据加密,如果攻击者截取了Web浏览器和网站服务器之间的传输报文,就可 ...

  5. 初入码田--ASP.NET MVC4 Web应用之创建一个空白的MVC应用程序

    初入码田--ASP.NET MVC4 Web应用开发之一  实现简单的登录 初入码田--ASP.NET MVC4 Web应用开发之二 实现简单的增删改查 2016-07-29 在此之前,需要一台电脑( ...

  6. 通过ClientDataSet复制表的结构及数据

    1.  需要2个ClientDataSet组件: 2.  clientDataSet1连接目标表,clientDataSet2连接源表,如果无法直接连接,使用DataSetProvider进行桥接: ...

  7. Java中线程安全的集合

    如果多线程并发的访问与一个数据结构,那么很容易破坏一个数据结构. 例如,一个线程可能要向一个散列表中插入一条数据的过程中,被剥夺了控制权.如果另外一个线程也开始遍历同一个链表,很可能造成混乱,抛出异常 ...

  8. Post Lamps CodeForces - 990E(暴力出奇迹?)

    题意: 在一个从0开始的连续区间上  放置几个小区间,使得这些小区间覆盖整个大区间,不同长度的小区间有不同的花费,其中有m个点,小区间的左端点不能放在这些点上 解析: 显然如果0是这m点中的一个 则无 ...

  9. loj2537 「PKUWC2018」Minimax 【概率 + 线段树合并】

    题目链接 loj2537 题解 观察题目的式子似乎没有什么意义,我们考虑计算出每一种权值的概率 先离散化一下权值 显然可以设一个\(dp\),设\(f[i][j]\)表示\(i\)节点权值为\(j\) ...

  10. 解题:BJOI 2006 狼抓兔子

    题面 可以看出来是最小割,然后你就去求最大流了 这么大的范围就是让你用网络流卡的?咋想的啊=.=??? 建议还是老老实实用 平面图最小割等于其对偶图最短路 这个东西来做吧,虽然这个东西跑的也挺慢的,最 ...