18 | metaclass,是潘多拉魔盒还是阿拉丁神灯?
蔡元楠
该思维导图由 AI 生成,仅供参考
你好,我是蔡元楠,极客时间《大规模数据处理实战》专栏的作者。今天我想和你分享的主题是:metaclass,是潘多拉魔盒还是阿拉丁神灯?
Python 中有很多黑魔法,比如今天我将分享的 metaclass。我认识许多人,对于这些语言特性有两种极端的观点。
一种人觉得这些语言特性太牛逼了,简直是无所不能的阿拉丁神灯,必须找机会用上才能显示自己的 Python 实力。
另一种观点则是认为这些语言特性太危险了,会蛊惑人心去滥用,一旦打开就会释放“恶魔”,让整个代码库变得难以维护。
其实这两种看法都有道理,却又都浅尝辄止。今天,我就带你来看看,metaclass 到底是潘多拉魔盒还是阿拉丁神灯?
市面上的很多中文书,都把 metaclass 译为“元类”。我一直认为这个翻译很糟糕,所以也不想在这里称 metaclass 为元类。因为如果仅从字面理解,“元”是“本源”“基本”的意思,“元类”会让人以为是“基本类”。难道 Python 的 metaclass,指的是 Python 2 的 Object 吗?这就让人一头雾水了。
事实上,meta-class 的 meta 这个词根,起源于希腊语词汇 meta,包含下面两种意思:
“Beyond”,例如技术词汇 metadata,意思是描述数据的超越数据;
“Change”,例如技术词汇 metamorphosis,意思是改变的形态。
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
- 深入了解
- 翻译
- 解释
- 总结
Python中的metaclass是一种强大的语言特性,具有超越类和变形类的能力。本文通过介绍metaclass的用途、应用方法以及Python底层语言设计层面的实现原理,深入探讨了metaclass的特性和使用方法。作者以YAMLObject为例,展示了metaclass的超越变形特性,说明了其在动态序列化/逆序列化方面的优势。此外,还介绍了metaclass的使用方法,以及Python底层语言设计层面是如何实现metaclass的。通过深入浅出的讲解,读者能够快速了解metaclass的概念及其在Python中的应用。文章还提到了使用metaclass的风险,指出了其可能对整个代码库造成的不可估量的风险,因此在应用层并不是很好的选择。总结指出,深入理解metaclass的Python开发者才能用好metaclass,而对于初学者则是科普和警告:不要轻易尝试metaclass。文章通过解读YAML的源码,围绕metaclass的设计本意“超越变形”,解析了metaclass的使用场景和使用方法,深入到Python语言设计层面,搞明白了metaclass的实现机制。文章以黑魔法级别的语言特性来形容metaclass,强调了使用好metaclass可以实现神奇的特性,但使用不好可能会打开潘多拉魔盒。
仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《Python 核心技术与实战》,新⼈⾸单¥59
《Python 核心技术与实战》,新⼈⾸单¥59
立即购买
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
登录 后留言
全部留言(65)
- 最新
- 精选
- 尘墨我尝试着自己写了一个例子,发现好像清晰多了,没有看懂的大家可以看一下 class Mymeta(type): def __init__(self, name, bases, dic): super().__init__(name, bases, dic) print('===>Mymeta.__init__') print(self.__name__) print(dic) print(self.yaml_tag) def __new__(cls, *args, **kwargs): print('===>Mymeta.__new__') print(cls.__name__) return type.__new__(cls, *args, **kwargs) def __call__(cls, *args, **kwargs): print('===>Mymeta.__call__') obj = cls.__new__(cls) cls.__init__(cls, *args, **kwargs) return obj class Foo(metaclass=Mymeta): yaml_tag = '!Foo' def __init__(self, name): print('Foo.__init__') self.name = name def __new__(cls, *args, **kwargs): print('Foo.__new__') return object.__new__(cls) foo = Foo('foo') 把上面的例子运行完之后就会明白很多了,正常情况下我们在父类中是不能对子类的属性进行操作,但是元类可以。换种方式理解:元类、装饰器、类装饰器都可以归为元编程(引用自 python-cook-book 中的一句话)。
作者回复: 棒
2019-06-20993 - KaitoShyyaml.load(""" --- !Monster name: Cave spider hp: [2,6] # 2d6 ac: 16 attacks: [BITE, HURT] """) 运行时报错,pyyaml版本PyYAML-5.1,将语句改成 yaml.load(""" --- !Monster name: Cave spider hp: [2,6] # 2d6 ac: 16 attacks: [BITE, HURT] """,Loader=yaml.Loader)即可,参见"https://github.com/yaml/pyyaml/issues/266"
作者回复: 很好
2019-06-1935 - TKbook一开始还以为我打开错专栏了。 目前看了好多解释metaclass的文章,感觉这一篇看起来最明了。
作者回复: 谢谢
2019-06-1924 - 隔壁家老鲍感觉入门了,不过还是有一些问题 @修饰符是在python里是怎么实现的呢 老师如果看到了可以给点意见么
作者回复: 问题很好,修饰器的确和metaclass有很多相似之处
2019-12-161 - jackstraw这代码跑都跑不通
作者回复: 遇到什么问题?这些代码我都校验过
2020-01-12 - 奔跑的蜗牛看不懂了 😄2019-06-195123
- =_=基础不够,之前没接触过metaclass,这一讲读起来太费劲了2019-06-1940
- 程序员人生装饰器像AOP,metaclass像反射机制2019-06-19135
- Hoo-Ah之前讲装饰器的时候讲到函数装饰器和类装饰器,而类装饰器就是在雷里面定义了__call__方法,之后在函数执行的时候会调用类的__call__方法。 在metaclass中重载了__call__方法,在使用metaclass实例化生成类的时候也是调用了__call__方法,从这方面来讲是很像。 要说不一样的话,一个是在执行层面,一个是在生成层面。 可以讲讲type和object的区别吗以及可以用一篇专栏讲讲python的魔术方法。2019-06-1927
- 建强1.metaclass拦截了类的构造,类似于黑客,改变了类的行为,在某些场合可简化程序设计。 2.python装饰器:不会去改变类的行为,但通过装饰类,可以加强类的功能,通过不同的装饰器使类的功能更加丰富。2019-09-2521
收起评论