Python元类__prepare__方法深入理解
学习元类的时候,对__prepare__不是很理解,书上讲解的也不是很详细,最后通过查看stackoverflow的一些帖子对该方法有了一些理解,记录如下:
先看代码:
class member_table(dict):
def __init__(self):
self.member_names = []
def __setitem__(self, key, value):
if key not in self:
self.member_names.append(key)
dict.__setitem__(self, key, value)
class OrderedClass(type):
@classmethod
def __prepare__(metacls, name, bases):
classdict = member_table()
print("prepare return dict id is:", id(classdict))
return classdict
def __new__(metacls, name, bases, classdict):
print("new get dict id is:", id(classdict))
result = type.__new__(metacls, name, bases, dict(classdict))
result.member_names = classdict.member_names
print("the class's __dict__ id is:", id(result.__dict__))
return result
def __init__(cls, name, bases, classdict):
print("init get dict id is ", id(classdict))
super().__init__(name, bases, classdict)
class MyClass(metaclass=OrderedClass):
def method1(self):
pass
def method2(self):
pass
print("MyClass locals() id is ", id(locals()))
输出为:
prepare return dict id is: 2093480992528
MyClass locals() id is 2093480992528
new get dict id is: 2093480992528
the class's __dict__ id is: 2093482830200
init get dict id is 2093480992528
可见,执行顺序为:
prepare(创建命名空间)-> 依次执行类定义语句 -> new(创建类)-> init(初始化类)
元类定义了prepare以后,会最先执行prepare方法,返回一个空的定制的字典,然后再执行类的语句,类中定义的各种属性被收集入定制的字典,最后传给new和init方法。
再来看其它输出:
MyClass.member_names
['__module__', '__qualname__', 'method1', 'method2']
MyClass.attr1 = 'attr1'
MyClass.__dict__
mappingproxy({'__dict__': <attribute '__dict__' of 'MyClass' objects>,
'__doc__': None,
'__module__': '__main__',
'__weakref__': <attribute '__weakref__' of 'MyClass' objects>,
'attr1': 'attr1',
'member_names': ['__module__',
'__qualname__',
'method1',
'method2'],
'method1': <function __main__.MyClass.method1>,
'method2': <function __main__.MyClass.method2>})
id(MyClass.__dict__)
2093482829864
MyClass.member_names
['__module__', '__qualname__', 'method1', 'method2']
上面的例子,在new方法中,dict被替换成一个普通的dict。所以MyClass.member_names不会记录class创建以后新增的属性。同时__dict__属性是类命名空间的一个代理,每次查看其id都不同。
3.6版本以前,prepare方法主要用来返回一个orderdict对象,以保存类中属性的添加顺序。而3.6版本以后,默认已经是保持顺序的了。
stackoverflow上的讨论帖
平时学习的一些笔记正在慢慢上传至github,欢迎大家交流。
地址是:https://github.com/telecomshy/python-study
Python元类__prepare__方法深入理解的更多相关文章
- Python进阶丨如何创建你的第一个Python元类?
摘要:通过本文,将深入讨论Python元类,其属性,如何以及何时在Python中使用元类. Python元类设置类的行为和规则.元类有助于修改类的实例,并且相当复杂,是Python编程的高级功能之一. ...
- Python 元类 - Metaclasses
Python 元类 - Metaclasses 默认情况下儿, classes 是有 type() 构造的. 类的结构体在一个新的 namespace 被执行, 类的名字 class name 绑定( ...
- Python元类实战,通过元类实现数据库ORM框架
本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是Python专题的第19篇文章,我们一起来用元类实现一个简易的ORM数据库框架. 本文主要是受到了廖雪峰老师Python3入门教程的启 ...
- python元类:type和metaclass
python元类:type和metaclass python中一切皆对象,所以类本身也是对象.类有创建对象的能力,那谁来创建类的呢?答案是type. 1.用tpye函数创建一个类 class A(ob ...
- Python元类之由浅入深
前言 元类属于python面向对象编程的深层次的魔法,非常重要,它使我们可以更好的掌控类从创建到消亡的整个生命周期过程.很多框架的源码中都使用到了元类.例如 Django Framework 中的 ...
- python元类理解2
恩,对元类理解又有新的收获,其实类似于装饰器,只不过装饰器是修饰函数,元类用来定制一个类. 代码如下,这是一个使用了函数做元类传递给类: input: def upper_attr(class_nam ...
- python元类深入理解
1.python 中的类 在python中,类也是一个对象,只不过这个对象拥有生成实例的能力,我们一般使用class XXX来定义一个类,在python解释器执行到这个地方的时候会自动创建出这个对象, ...
- python 元类理解
原文来自:https://segmentfault.com/a/1190000011447445 学懂元类,你只需要知道两句话: 道生一,一生二,二生三,三生万物 我是谁?我从哪来里?我要到哪里去? ...
- 深入理解python元类
类也是对象 在理解元类之前,你需要先掌握Python中的类.Python 中的类概念借鉴 Smalltalk,这显得有些奇特.在大多数编程语言中,类就是一组用来描述如何生成一个对象的代码段.当然在 P ...
随机推荐
- Python常用算法
本节内容 算法定义 时间复杂度 空间复杂度 常用算法实例 1.算法定义 算法(Algorithm)是指解题方案的准确而完整的描述,是一系列解决问题的清晰指令,算法代表着用系统的方法描述解决问题的策略机 ...
- Hadoop介绍及集群搭建
简介 Hadoop 是 Apache 旗下的一个用 java 语言实现开源软件框架,是一个开发和运行处理大规模数据的软件平台.允许使用简单的编程模型在大量计算机集群上对大型数据集进行分布式处理.它的核 ...
- 【光速使用开源框架系列】数据库框架OrmLite
[关于本系列] 最近看了不少开源框架,网上的资料也非常多,但是我认为了解一个框架最好的方法就是实际使用.本系列博文就是带领大家快速的上手一些常用的开源框架,体会到其作用. 由于作者水平有限,本系列只会 ...
- Nginx Rewrite研究笔记
原文出自:http://blog.cafeneko.info/2010/10/nginx_rewrite_note/ 在新主机的迁移过程中,最大的困难就是WP permalink rewrite的设置 ...
- Oracle树查询,start with connect by prior 递归查询用法(转载)
本人觉得这个写的真不错,实用性强,就转载过来了 这个子句主要是用于B树结构类型的数据递归查询,给出B树结构类型中的任意一个结点,遍历其最终父结点或者子结点. 先看原始数据: 1 create tabl ...
- 虚拟机ubuntu18.04设置静态IP
说明: 网关:192.168.8.2 待设置静态IP:192.168.8.25 1.编辑:vi /etc/netplan/01-network-manager-all.yaml 打开以后内容如下: # ...
- ubunt 14.04 Could not find CMAKE_ROOT !!! CMake has most likely not been installed correctly. Modul
CMake Error: Could not find CMAKE_ROOT !!! CMake has most likely not been installed correctly. Modul ...
- PHP中static与self
一直搞不清楚,今天百度自己也测试了一下. <?php class A { public static function closure(){ echo __CLASS__."<b ...
- rpmbuild spec 打包jar变小了、设置禁止压缩二进制文件Disable Binary stripping in rpmbuild
Disable Binary stripping in rpmbuild 摘自:http://livecipher.blogspot.com/2012/06/disable-binary-stripp ...
- Python基础入门-集合
今天给大家分享的是python中集合(set)的概念,集合这个词其实和高中学的数学集合的概念很相近,或者作为初学者你就可以把它理解为数学当中的集合.在python中集合(set)是由一个个键组成的,但 ...