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 ...
随机推荐
- 【原】Coursera—Andrew Ng机器学习—Week 3 习题—Logistic Regression 逻辑回归
课上习题 [1]线性回归 Answer: D A 特征缩放不起作用,B for all 不对,C zero error不对 [2]概率 Answer:A [3]预测图形 Answer:A 5 - x1 ...
- Scala介绍
强大的编程语言 Scala 是一门非常强大的语言,它允许用户使用命令和函数范式进行编写代码,因此,编程时你可以使用常用的命令式语句,就像我们使用 C.Java.PHP 以及很多其他语言一样,而且,你也 ...
- java基础之多线程四:简单案例
多线程案例: 有一个包包的数量为100个,分别从实体店和官网进行售卖.使用多线程的方式,分别打印实体店和官网卖出包包的信息.分别统计官网和实体店各卖出了多少个包包 第一种方法 继承Thread类: p ...
- cocos2d-x 初探helloWorld
cocos2d-x的main函数代码很少,把一些复杂的接口封装到AppDelegate类里了,“AppDelegate”从词意可以得出是app的代理类,而一些最早的场景都会在AppDelegate类里 ...
- 公共技术点之 Java 反射 Reflection
本文摘录地址: http://codekk.com/open-source-project-analysis/detail/Android/Mr.Simple/%E5%85%AC%E5%85%B1%E ...
- ROS导航包的介绍
博客转载自:https://blog.csdn.net/handsome_for_kill/article/details/53130707#t3 ROS导航包的应用 利用ROS Navigation ...
- 在Linux中监视IO性能
dd命令 iostat命令 理解iostat的各项输出 iostat的应用实例 附:在Windows中监视IO性能 延伸阅读 dd命令 dd其实是工作于比较低层的一个数据拷贝和转换的*nix平台的工具 ...
- Luogu 3665 [USACO17OPEN]Switch Grass 切换牧草
BZOJ 4777 被权限了. 这道题的做法看上去不难,但是感觉自己yy不出来. 首先是两个结论: 1.答案一定是连接着两个异色点的一条边. 2.答案一定在最小生成树上. 感觉看到了之后都比较显然,自 ...
- TabbedPane标签美化式样自定义
JTabbedPane标签美化式样自定义 摘自:https://blog.csdn.net/yuanzihui/article/details/43936795 通过继承BasicTabbedPane ...
- C++语法知识小结(持续更新中)
1)在适用构造函数创建对象时,有时会创建临时对象.如 Stock::Stock(const std::string & co,long n,double pr); 在使用时,下面两条语句有根本 ...