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 。


640.png


当使用 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 真的就只学会了篮球。。。


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

相关文章
|
1月前
|
测试技术 Python
Python中的装饰器:概念、用法和应用
【4月更文挑战第6天】 装饰器是Python中的一个重要概念,它允许我们在不修改原始函数代码的情况下,增加或修改函数的行为。本文将深入探讨装饰器的概念、用法和应用,帮助读者更好地理解和使用这一强大的工具。
|
2月前
|
测试技术 Python
Python中的装饰器:概念、用法及实例
【2月更文挑战第25天】 装饰器在Python中是一种强大的工具,它允许我们在不修改原始函数代码的情况下,增加函数的功能。本文将深入探讨装饰器的概念,解析其工作原理,并通过实例来展示如何在Python中使用装饰器。
|
2月前
|
Python
请简述Python中的继承、封装和多态的概念。
【2月更文挑战第24天】【2月更文挑战第82篇】请简述Python中的继承、封装和多态的概念。
|
12天前
|
机器学习/深度学习 算法 数据挖掘
【Python 机器学习专栏】Python 机器学习入门:基础概念与流程
【4月更文挑战第30天】本文介绍了Python在机器学习中的重要性,机器学习的基础概念和分类,包括监督学习、非监督学习和强化学习。Python因其丰富的库(如Scikit-learn、TensorFlow、PyTorch)、简单易学的语法和跨平台性在机器学习领域广泛应用。文章还概述了机器学习的基本流程,包括数据收集、预处理、特征工程、模型训练与评估等,并列举了常用的Python机器学习算法,如线性回归、逻辑回归、决策树和支持向量机。最后,讨论了Python机器学习在金融、医疗、工业和商业等领域的应用,鼓励读者深入学习并实践这一技术。
|
17天前
|
存储 开发工具 数据库
云计算:概念、优势与实践——附Python代码示例
云计算:概念、优势与实践——附Python代码示例
|
18天前
|
数据可视化 Python
R语言和Python对copula模型Gaussian、t、Clayton 和Gumbel族可视化理论概念和文献计量使用情况
R语言和Python对copula模型Gaussian、t、Clayton 和Gumbel族可视化理论概念和文献计量使用情况
|
18天前
|
Python
Python从入门到精通:深入学习面向对象编程——2.1.2继承、封装和多态的概念
Python从入门到精通:深入学习面向对象编程——2.1.2继承、封装和多态的概念
|
18天前
|
机器学习/深度学习 人工智能 运维
Python从入门到精通:1.1.2了解Python基本概念与安装Python环境
Python从入门到精通:1.1.2了解Python基本概念与安装Python环境
|
19天前
|
消息中间件 安全 调度
Python从入门到精通:3.1.1多线程与多进程——进程和线程的概念
Python从入门到精通:3.1.1多线程与多进程——进程和线程的概念
|
19天前
|
机器学习/深度学习 人工智能 运维
Python从入门到精通:1.1 .1了解Python基本概念
Python从入门到精通:1.1 .1了解Python基本概念