python 3 黑色魔法元类初探
最近读django源码,发现必须了解元类才能理解一些很神奇的行为.
发现元类实际上是控制class的创建过程.比如类B继承某个看似平淡无奇的类A之后,你在类B中定义的属性或方法可能会遭到彻底改变.
假设我们想实现这么一种需求:
创建一个类Child,在这个类中定义的种种字符串属性,都可以当做对应的函数那样调用.例如:
class Child():
f1='print'
随后,Child.f1就完全和内建函数print等价了.Child.f1('abc')能够打印出abc这个字符串.
这样来说,元类的用途看起来可以是:一些高手设计了一个在幕后做了很多工作的元类,另一些开发人员只需要简单地继承这个元类或者这个元类的子类,敲几个属性定义的代码,就能实现很多复杂的功能.django就是这样的.比如它的model.Models就充分利用了这种魔法.
下面从代码层面展示元类具体是怎么运作的:
class MyMeta(type):
def __new__(cls, name, parents, attrs):
for k,v in locals().items():
if isinstance(v,dict):
for k2,v2 in v.items():
print(k,'|',k2,'|',type(v2),'|',v2)
else:
print(k,'|',v)
return type.__new__(cls, name, parents, attrs) class Parent1(type):
pass class Parent2(object):
pass class Parent3():
pass class AbstractChild(Parent1,Parent2,Parent3,metaclass=MyMeta):
pass class Child(AbstractChild): f1 = 1
f2 = sorted
f3 = int class classinchild():
pass @staticmethod
def stcm():
pass @classmethod
def clsm(cls):
pass def insm(self):
pass print('-'*60) class EvalMeta(type):
def __new__(cls, name, parents, attrs):
new_attrs={}
for k,v in attrs.items():
if not k.startswith('__') and isinstance(v,str):
new_attrs[k] = eval(v)
else:
new_attrs[k] = v
return type.__new__(cls, name, parents, new_attrs) class AbstractChild(metaclass=EvalMeta):
pass class Child(AbstractChild):
f1='print'
f2='sorted' if __name__=='__main__':
x=Child()
x.f1('invoke f1 as print function')
print('invoke f2 as sorted function:',Child.f2([3,2,1]))
结果:
>>>
name | AbstractChild
cls | <class '__main__.MyMeta'>
parents | (<class '__main__.Parent1'>, <class '__main__.Parent2'>, <class '__main__.Parent3'>)
attrs | __module__ | <class 'str'> | __main__
attrs | __qualname__ | <class 'str'> | AbstractChild
name | Child
cls | <class '__main__.MyMeta'>
parents | (<class '__main__.AbstractChild'>,)
attrs | stcm | <class 'staticmethod'> | <staticmethod object at 0x0000000003075C50>
attrs | clsm | <class 'classmethod'> | <classmethod object at 0x000000000309CA58>
attrs | __module__ | <class 'str'> | __main__
attrs | insm | <class 'function'> | <function Child.insm at 0x0000000003139400>
attrs | __qualname__ | <class 'str'> | Child
attrs | f1 | <class 'int'> | 1
attrs | f3 | <class 'type'> | <class 'int'>
attrs | f2 | <class 'builtin_function_or_method'> | <built-in function sorted>
attrs | classinchild | <class 'type'> | <class '__main__.Child.classinchild'>
------------------------------------------------------------
invoke f1 as print function
invoke f2 as sorted function: [1, 2, 3]
>>>
python 3 黑色魔法元类初探的更多相关文章
- python基础——使用元类
python基础——使用元类 type() 动态语言和静态语言最大的不同,就是函数和类的定义,不是编译时定义的,而是运行时动态创建的. 比方说我们要定义一个Hello的class,就写一个hello. ...
- Python基础:元类
一.概述 二.经典阐述 三.核心总结 1.类的创建过程 2.元类的使用惯例 四.简单案例 1.默认行为 2.使用元类 五.实践为王 一.概述 Python虽然是多范式的编程语言,但它的数据模型却是 纯 ...
- Python中的元类(metaclass)
推荐+收藏:深刻理解Python中的元类(metaclass) 做一些笔记学习学习: 在大多数编程语言中,类就是用来描述如何生成一个对象的代码段,在Python中类也是一个对象,这个(类)对象自身拥有 ...
- [转]深刻理解Python中的元类(metaclass)以及元类实现单例模式
使用元类 深刻理解Python中的元类(metaclass)以及元类实现单例模式 在看一些框架源代码的过程中碰到很多元类的实例,看起来很吃力很晦涩:在看python cookbook中关于元类创建单例 ...
- 什么是python中的元类
所属网站分类: python高级 > 面向对象 作者:goodbody 原文链接: http://www.pythonheidong.com/blog/article/11/ 来源:python ...
- Python之面向对象元类
Python之面向对象元类 call方法: class People: def __init__(self,name): self.name=name # def __call__(self, *ar ...
- [Python之路] 元类(引申 单例模式)
一.类也是对象 当我们定义一个变量或者函数的时候,我们可以在globals()的返回值字典中找到响应的映射: def A(): print("This is function A" ...
- Python 中的元类到底是什么?这篇恐怕是最清楚的了
类作为对象 在理解元类之前,您需要掌握 Python 的类.Python 从 Smalltalk 语言中借用了一个非常特殊的类概念. 在大多数语言中,类只是描述如何产生对象的代码段.在 Python ...
- Python面向对象06 /元类type、反射、函数与类的区别、特殊的双下方法
Python面向对象06 /元类type.反射.函数与类的区别.特殊的双下方法 目录 Python面向对象06 /元类type.反射.函数与类的区别.特殊的双下方法 1. 元类type 2. 反射 3 ...
随机推荐
- 【Swift】ios开发中巧用 description 打印对象时,打印对象的属性
ios开发中我们打印对象的时候,会直接输出对象地址,这样不方便我们开发.我们可以 巧用 description 打印对象时,输出对象的属性 在oc中直接重写即可.swift中需要遵守Printable ...
- 机器学习基石:01 The Learning Problem
什么时候适合用机器学习算法? 1.存在某种规则/模式,能够使性能提升,比如准确率: 2.这种规则难以程序化定义,人难以给出准确定义: 3.存在能够反映这种规则的资料. 所以,机器学习就是设计算法A,从 ...
- [Codeforces 961G]Partitions
Description 题库链接 给你 \(n\) 个不同的元素组成的集合 \(R\) ,每个元素有一个权值 \(w\) .对于一个子集集合 \(S\) ,它的价值为 \(W(S)=|S|\cdot\ ...
- [UVa 1326]Jurassic Remains
题解 在一个字符串中,每个字符出现的次数本身是无关紧要的,重要的只是这些次数的奇偶性,因此想到用一个二进制的位表示一个字母($1$表示出现奇数次,$0$表示出现偶数次).比如样例的$6$个数,写成二进 ...
- codeforces 868B Race Against Time
Have you ever tried to explain to the coordinator, why it is eight hours to the contest and not a si ...
- 亲戚(relative)
[题目背景] Y 家是世界上最大的家族,HJZ 是其中一员. 现在 Y 家人想要拍一张全家福,却发现这是一个十分复杂的问题. . . . . . [题目描述] Y 家一共有 n 人 其中每个人最多有一 ...
- weak_ptr解决shared_ptr环状引用所引起的内存泄漏[转]
转载:http://blog.csdn.net/liuzhi1218/article/details/6993135 循环引用: 引用计数是一种便利的内存管理机制,但它有一个很大的缺点,那就是不能管理 ...
- reserve的使用
reserve: 强迫容器将它的容量变成n 可以避免不必要的重新分配 如果n大于当前容量,那么正常. 如果n小于当前容量,vector会忽略,string则是减小为 max(size(),n). 如果 ...
- SPFA小总结
关于spfa 知识点 原始版 ---裸 应用: 一.判负环 两种方法 1.跑单源点bfs,如果某一个点入队了n-1次,存在 2.对于每个点dfs,如果此源点反被其他点更新,存在 证明:点i作为源点,d ...
- [APIO/ctsc2007]
A.风铃 给一棵二叉树,叶子结点是玩具,为使你的弟弟满意,你需要选一个满足下面两个条件的风铃: (1) 所有的玩具都在同一层(也就是说,每个玩具到天花板之间的杆的个数是一样的)或至多相差一层.(2) ...