专栏首页机器学习与统计学Python 中最黑魔法、最难懂的概念

Python 中最黑魔法、最难懂的概念

大家好,我是老胡

最近在看一个开源框架的源码,其中大量使用了 metaclass 方法。这个概念非常抽象,本文我就以一个有趣实例,用更简洁和通畅的方式来理解它。

元类 ( metaclass )应该是 Python 中最黑魔法、最难懂的概念之一,它提供了创造新类型的能力,为程序设计带来更多可能性。不少功能强大的开发框架,内部实现离不开 metaclass 的魔法。

Class

面向对象编程最重要的概念就是类(Class)和实例(Instance),我们先来创建一个 Lxs 的类,它有两个基本功 sing 和 dance ,lxs 是这个类的实例:

class Lxs(object): 
    def __init__(self, name, duration):
        self.name = name
        self.duration = duration
        print('%s practiced %s years' % (self.name, self.duration))
    def sing(self):
        print('%s good at singing' % self.name)

    def dance(self):
        print('%s good at dancing' % self.name)

lxs = Lxs('laohu',1.5)
lxs.sing()
lxs.dance()

练习时常1年半的老胡擅长唱和跳 恩,针不戳!

laohu practiced 1.5 years
laohu good at singing
laohu good at dancing

再来用__class__属性或type()看看 Lxs 和 lxs 分别是谁创建的

print(lxs.__class__)
print(Lxs.__class__)

lxs 是 Lxs 的实例,它创建自 Lxs ,这很容易理解。

我们 Lxs 类是 type 创建的?

<class '__main__.Lxs'>
<class 'type'>

一切对象都来自 type

先说结论:type 可以动态创建 类(class) ,对象是类(class)的实例,类(class)也是对象,是 type 的实例。type 为对象的顶点,所有对象都创建自 type 。

当使用 type 创建 class 时,其用法如下:

class = type(classname, superclasses, attributedict)
'''
classname:类名
superclasses:类的继承关系,用元组表示
attributedict:表示各种属性、方法,用字典表示
'''

继续上例,先定义__init__,sing 和 dance ,然后用 type 可以创建和上面完全一样的类:

Lxs = type('Lxs', (object,), dict( __init__= __init__,sing=sing,dance=dance))
lxs = Lxs('laohu',1)
lxs.sing()
print(lxs.__class__)
print(Lxs.__class__)

这里不得不提一下__call__这个属性 此方法会在实例作为一个函数被“调用”时被调用 这里等号右边的type(classname, superclasses, attributedict),就是 type 的__call__运算符重载,它会进一步调用:

type.__new__(typeclass, classname, superclasses, attributedict)
type.__init__(class, classname, superclasses, attributedict)
# 这一部分我们以后有空再细品

总结一下:type 实际上是 Python 创建所有 class 的 metaclass。

metaclass

除了使用type()动态创建类以外,要控制类的创建行为,还可以使用metaclass。

先定义metaclass,就可以创建类,最后创建实例。

一句话:metaclass 是 type 的子类,是类的模板

metaclass 的主要目的是在 class 被创建的时候对生成的 class 进行自动的动态修改。

举个例子:像老胡就只会 sing 和 dance,有人还会rap,有人会说相声,我们定义很多的 class ,有一天,一个男人横空出世,他会打篮球!然后,所有的练习生也都学会了篮球,这可怎么修改?

metaclass 就可以施展魔法了

class LxsMetaclass(type):
    def __new__(cls, cls_name, bases, attrs):
        def basketball(self):
            print('%s good at basketball' % self.name)
        attrs['basketball'] = basketball
        return super(LxsMetaclass, cls).__new__(cls, cls_name, bases, attrs)

它指示Python解释器在创建 LxsMetaclass 时,要通过LxsMetaclass.new()来创建,在此,我们可以修改类的定义,比如,加上新的方法basketball(),然后,返回修改后的定义。

我们用 LxsMetaclass 这个模板创建类:

class Cxk(object, metaclass=LxsMetaclass):
    def __init__(self, name, duration):
        self.name = name
        self.duration = duration
        print('%s practiced %s years' % (self.name, self.duration))
    
    def sing(self):
        print('%s good at singing' % self.name)
    
    def dance(self):
        print('%s good at  dancing' % self.name)
    
    def rap(self):
        print('%s good at  rap' % self.name)

    
cxk = Cxk('cxk',2.5)
cxk.basketball()

运行结果如下,秀?

cxk practiced 2.5 years
cxk good at basketball

不过metaclass的作用肯定不限于此,举个例子,也算是个思考题,大家品一品。

比如 laohu 化身 xck 的粉丝,打着学篮球的幌子学 sing、dance和rap :

class Funs(Cxk):
    def basketball(self):
        print('%s good at  singing&dancing&rap' % self.name)


fans = Funs('laohu',0.5)
fans.basketball()

运行结果会是什么呢?

laohu practiced 0.5 years
laohu good at basketball

laohu 真的就只学会了篮球。。。

这是为何呢?且听下回分解。

兄弟们,来个三连可好?转发,在看,点赞

本文分享自微信公众号 - 机器学习与统计学(tjxj666),作者:student老胡

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2021-04-15

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 《假如编程是魔法之零基础看得懂的Python入门教程 》——(四)了解魔法百宝箱列表、字典及基本数据类型

    在编程中经常会遇见某些值需要存储,就像上一节内容input的使用一样,如果没有一个容器存储输入的值,可能就会原地输出了,很多情况下这样使用并没有太大的意义。例如...

    公众号 碧油鸡
  • 龙妈非主角?AI告诉你下一个谁领便当:机器学习解读《冰与火之歌》

    永远不知道谁会下一个领便当的《权力的游戏》迎来了最终季。就在昨天,在全球粉丝的热切期盼下,HBO播出了《权力的游戏》第八季第一集,这首冰与火之歌终于奏响终章了。

    量子位
  • 《假如编程是魔法之零基础看得懂的Python入门教程 》——(二)魔法实习生第一步了解魔杖的使用

    对于很多第一次学习编程的同学对于很多定义性的概念大多都不了解,例如开发环境。对于大部分同学来说这是个模糊的概念。

    公众号 碧油鸡
  • 《假如编程是魔法之零基础看得懂的Python入门教程 》——(三)使用初始魔法跟编程魔法世界打个招呼吧

    python是一种对比C、C++、Java等语言来说是一种极其易用的语言。在编程学习上来说,通过python的学习会帮助我们了解编程世界,可以更好的学习一些比p...

    公众号 碧油鸡
  • Python系列文章汇总

    经过一个多月的努力,终于把 Python 相关的文章更新完毕,这些文章主要包括两大模块:爬虫系列和 Python 进阶系列。

    _Kaito
  • “备孕期”的Java程序员一定要学会抽象 | 《Java编程思想拆书》

    我相信,看到标题后的你一定很好奇,究竟什么样的Java程序员算是在“备孕期”呢?在我看来,“备孕期”主要指那些初入Java编程的新人,他们正下足功夫准备,以求在...

    沉默王二
  • 怎样去阅读源码,这篇文章值的你一读

    作者:刘欣 公众号:码农翻身 链接:http://mp.weixin.qq.com/s/PDhEKM2XG_qzOmBjWb-M7Q "没有经验的技术...

    hbbliyong
  • Python 元类(MetaClass)

    Python 动态语言的动态特性 Python是解释运行的动态语言,它与Java最大的不同是Java的类和方法是在编译时完成定义的,而对Python来说,...

    Steve Wang
  • 编辑了基因,就能成为人生赢家?5本书给你答案

    导读:11月26日,据人民网的一则报道,世界首例免疫艾滋病基因编辑婴儿在中国诞生。消息传出后,巨大的争议随之而来。122位科学家联名谴责这项研究,称“潘多拉魔盒...

    华章科技
  • 教程 | 十分钟学会函数式 Python

    函数式编程到底是什么?本文将详解其概念,同时分享怎样在 Python 中使用函数式编程。主要内容包括列表解析式和其他形式的解析式。

    昱良
  • 教程 | 十分钟学会函数式 Python

    导读:函数式编程到底是什么?本文将详解其概念,同时分享怎样在 Python 中使用函数式编程。主要内容包括列表解析式和其他形式的解析式。

    1480
  • 教程 | 十分钟学会函数式 Python

    导读:函数式编程到底是什么?本文将详解其概念,同时分享怎样在 Python 中使用函数式编程。主要内容包括列表解析式和其他形式的解析式。

    Python数据科学
  • 有了这 15 款编程游戏,谁都可以学编程!

    一边玩游戏,一边挑战编程难题。Coding games支持包括PHP、C、JavaScript在内的20多种编程语言。用户界面功能强大,可以定制。

    五分钟学算法
  • 一个优秀的产品经理该如何做好数据分析?|数据分析

    这两年,随着大数据、精益化运营、增长黑客等概念的传播,数据分析的思维越来越深入人心。处于互联网最前沿的产品经理们接触了大量的用户数据,但是却一直困扰于如何做好数...

    陆勤_数据人网
  • 边玩游戏边学编程,怎么做到的?!

    经常听到有朋友说,学习编程是一件非常枯燥无味的事情。其实,大家有没有认真想过,可能是我们的学习方法不对?

    GitHubDaily
  • 字节跳动后端实习面经,一面+二面

    本来约的今天下午2点一面,一面完面试官让我直接等二面,然后就连着面了,二面完面试官又让我等着直接三面,然后等了一会儿说三面面试官不在,下次约时间。。。。看来是打...

    烂猪皮
  • 习题34:模块,类,对象

    创建一个名字叫mystuff.py文件,并且在里面放了个叫做apple的函数,代码如下

    py3study
  • python基础篇(四)——Python数据类型之列表(中)

      上篇文章给大家介绍了列表的相关知识。包括列表的概念以及列表的增删改查,最后还介绍了列表的排序和应用列表应该注意事项。本文给大家介绍列表的相关操作,包括遍历整...

    一计之长
  • 码农的数学和算法入门

    虽然是段子,但其实也挺写实的,因为你打开各大招聘网站,会发现越是高薪的IT岗位,对数学的要求越高。其实,我曾经也不太明白数学为什么对程序员很重要,不明白为什么在...

    FunTester

扫码关注云+社区

领取腾讯云代金券