深入浅出Python元编程,不仅仅是Metaclass

2023-12-29 06:32

本文主要是介绍深入浅出Python元编程,不仅仅是Metaclass,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

隔壁的Java 世界为了创建一个对象搞得鸡飞狗跳,这边的Python解释器倒是乐得清闲。 (参见:《当创建对象时......》)

 

我作为他的第n任助手正式上岗。

Python基础教程|深入浅出Python元编程,不仅仅是Metaclass

更多Python视频、源码、资料加群683380553免费获取

“老大,有程序员要创建对象,怎么办?”我向Python解释器发出了预警,上岗后头一次遇到这种情况,我有点紧张。

class Person:def sayHello(self,name):print("hello,"+name)
p = Person()
p.sayHello("andy")

“怕啥,我告诉你怎么做啊,首先找到Metaclass(元类),用元类来创建Class, 最后用Class对象来创建实例。” 老大说着还给我画了个图:

 

Python基础教程|深入浅出Python元编程,不仅仅是Metaclass

 

“不是吧!刚才还说人家Java鸡飞狗跳,我看我们这儿也丝毫不差,一个Class(如Person)在内存中用个对象来表示我理解,毕竟在我们的世界中,一切都是对象嘛, 但是这Metaclass(元类)是什么鬼?”

“是啊,类是一个对象,调用这个类对象的__new__方法就可以创建出这个类的实例。那么问题来了, 类对象是怎么来的?怎么把这个类对象给new 出来?” 老大没有回答,只是反问。

“不是程序员写的吗, class Person.....” 我有点底气不足。

“程序员写的只是代码,都是文本而已,我们在执行的过程中需要用Metaclass 把这个Person类对象给创建起来的。”

“可是我也没有看到Person类的Metaclass啊?! 他到底在哪儿?”

“那是你没有找到, Person类中没有,就去它的父类中去找,如果也没有,就继续向父类的父类去找,如果在任何父类中都找不到Metaclass,就去模块中去找,如果还是找不到,就用缺省的Metaclass,即type。”

我按照老大的要求,去找这个Metaclass,没有找到,只好用缺省的type了。

可是我记得这个type不是个类,是个函数啊,可以用来查看一个变量的类型:

>>> type(1)
<class 'int'>
>>> type("aaa")
<class 'str'>
>>>

老大说:“这个type啊,还有另外一个用法,可以创建其他类对象,在创建的时候,需要三个参数:”

1. 要创建的类对象的名称,例如"Person"

2. 要创建的类对象的父类,例如(object,)

3. 包含属性的字典,即类的属性和方法。例如{"sayHello": sayHello}

比如,下面这段代码也创建了一个类对象Person,和程序员写的class Person... 效果是一样的。

def sayHello(self,name):print("hello,"+name)
#通过type来创建一个类对象,名称为Person,这个类对象有一个方法sayHello
Person = type("Person",(),{"sayHello":sayHello})
#通过类对象来创建实例
p = Person()
p.sayHello("andy") # hello andy 

 

嘿,这个办法不错啊,可以在运行时、动态地创建一个全新的类出来!隔壁的Java虽然也能做到,但是得利用ASM之类工具去直接操作字节码,太麻烦了,我大Python直接通过普普通通、简简单单的Python代码就搞定了!

这就是动态脚本语言的一个优势吧!

之前听说过元编程,现在应该就是元编程了吧?但是这个Metaclass到底有什么用处呢? 程序员为什么不直接在代码中写class Person..... 这样的代码? 这样多直观啊。

老大说:“有些程序员会自定义Metaclass,这些自定义的Metaclass 主要做这些事情:”

1. 拦截类的创建

2. 读取类的信息,可能做修改

3. 返回新的类。

拦截类的创建? 为什么有这样“变态”的需求?

我真想看看一个自定义的Metaclass,看看它到底是怎么“变态”的。

没多久,机会来了,又要创建对象了。

from django.db import models
class Employee(models.Model):name = models.CharField(maxlength = 50) age = models.IntegerField()#其他代码略#

在Employee中没有看到Metaclass, 我就去父类Model中去寻找,运气不错,一下子就找到了metaclass ,叫做ModelBase:

class Model(metaclass=ModelBase):#其他代码略

赶紧去看ModelBase的代码,唉,实在是有点复杂了,让我看得头晕。

老大说:“你不用花费时间了,你的前任的前任曾经研究过它,是为了实现ORM !”

“ORM?”

“就是对象和关系数据库的映射。你想想,程序员创建的Python对象想要保存到数据库中,该怎么办?“ 老大问道。

”那还不简单,程序员可以写SQL代码啊,insert into employee(name,age) values(?,?),其中包含那个Employee对象的name ,age的值不就行了?“

”那样就有点笨拙了,你再想想,能不能简化程序员的工作,别让他们去写这些烦人的、容易出错的SQL代码?能不能让框架来做这件事?“ 老大写了两行代码。

employee = Employee(name="andy",age=20) 
employee.save()

“看看,程序员只要把对象创建出来,调用下save方法就行了,SQL语句就会形成,保存到数据库中。”

(注:这里略过了数据库连接的管理)

“难道ModelBase这个元类在后面做‘手脚'?”我似乎有点理解了。

”没错,你看到这些Employee类的属性没有? 就是程序员写的那些name, age...... 程序员这么写,其实就是在告诉ModelBase,尊敬的Metaclass 啊, 这些都是数据库的列啊,列名是 name, 类型是char(50) , 还有个列名是age,是个整数。”

 

Python基础教程|深入浅出Python元编程,不仅仅是Metaclass

 

“那个MetaClass ,对,就是ModelBase会读取这些列名、类型,并且记录下来。 有了列名的信息,将来就可以形成insert, update,delete等SQL语句了。对不对?”

原来如此!看来ModelBase在创建Employee类对象的时候,“偷偷地”读取了Employee类的定义信息,这样才能在背后实现ORM!

 

Python基础教程|深入浅出Python元编程,不仅仅是Metaclass

 

我按照老大的指示,调用ModelBase的__new__方法,创建了Employee类对象。

接下来又调用Employee类对象的__new__方法,创建了Employee实例对象。

employee = Employee(name="andy",age=20) 
employee.save()

当程序员调用employee.save()方法的时候,正如老大所说,神奇的魔法发生了,一条sql语句形成,并且发送给了数据库去执行。

我感慨到:“这Python的元编程还是真是不错啊,能在运行时动态地修改类,比隔壁的Java强多了!”

“Python元编程的技术不仅仅是Metaclass,还多着呢,你慢慢学吧!”

这篇关于深入浅出Python元编程,不仅仅是Metaclass的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/548625

相关文章

使用Python删除Excel中的行列和单元格示例详解

《使用Python删除Excel中的行列和单元格示例详解》在处理Excel数据时,删除不需要的行、列或单元格是一项常见且必要的操作,本文将使用Python脚本实现对Excel表格的高效自动化处理,感兴... 目录开发环境准备使用 python 删除 Excphpel 表格中的行删除特定行删除空白行删除含指定

Python通用唯一标识符模块uuid使用案例详解

《Python通用唯一标识符模块uuid使用案例详解》Pythonuuid模块用于生成128位全局唯一标识符,支持UUID1-5版本,适用于分布式系统、数据库主键等场景,需注意隐私、碰撞概率及存储优... 目录简介核心功能1. UUID版本2. UUID属性3. 命名空间使用场景1. 生成唯一标识符2. 数

Python办公自动化实战之打造智能邮件发送工具

《Python办公自动化实战之打造智能邮件发送工具》在数字化办公场景中,邮件自动化是提升工作效率的关键技能,本文将演示如何使用Python的smtplib和email库构建一个支持图文混排,多附件,多... 目录前言一、基础配置:搭建邮件发送框架1.1 邮箱服务准备1.2 核心库导入1.3 基础发送函数二、

Python包管理工具pip的升级指南

《Python包管理工具pip的升级指南》本文全面探讨Python包管理工具pip的升级策略,从基础升级方法到高级技巧,涵盖不同操作系统环境下的最佳实践,我们将深入分析pip的工作原理,介绍多种升级方... 目录1. 背景介绍1.1 目的和范围1.2 预期读者1.3 文档结构概述1.4 术语表1.4.1 核

基于Python实现一个图片拆分工具

《基于Python实现一个图片拆分工具》这篇文章主要为大家详细介绍了如何基于Python实现一个图片拆分工具,可以根据需要的行数和列数进行拆分,感兴趣的小伙伴可以跟随小编一起学习一下... 简单介绍先自己选择输入的图片,默认是输出到项目文件夹中,可以自己选择其他的文件夹,选择需要拆分的行数和列数,可以通过

Python中反转字符串的常见方法小结

《Python中反转字符串的常见方法小结》在Python中,字符串对象没有内置的反转方法,然而,在实际开发中,我们经常会遇到需要反转字符串的场景,比如处理回文字符串、文本加密等,因此,掌握如何在Pyt... 目录python中反转字符串的方法技术背景实现步骤1. 使用切片2. 使用 reversed() 函

Python中将嵌套列表扁平化的多种实现方法

《Python中将嵌套列表扁平化的多种实现方法》在Python编程中,我们常常会遇到需要将嵌套列表(即列表中包含列表)转换为一个一维的扁平列表的需求,本文将给大家介绍了多种实现这一目标的方法,需要的朋... 目录python中将嵌套列表扁平化的方法技术背景实现步骤1. 使用嵌套列表推导式2. 使用itert

使用Docker构建Python Flask程序的详细教程

《使用Docker构建PythonFlask程序的详细教程》在当今的软件开发领域,容器化技术正变得越来越流行,而Docker无疑是其中的佼佼者,本文我们就来聊聊如何使用Docker构建一个简单的Py... 目录引言一、准备工作二、创建 Flask 应用程序三、创建 dockerfile四、构建 Docker

Python使用vllm处理多模态数据的预处理技巧

《Python使用vllm处理多模态数据的预处理技巧》本文深入探讨了在Python环境下使用vLLM处理多模态数据的预处理技巧,我们将从基础概念出发,详细讲解文本、图像、音频等多模态数据的预处理方法,... 目录1. 背景介绍1.1 目的和范围1.2 预期读者1.3 文档结构概述1.4 术语表1.4.1 核

Python使用pip工具实现包自动更新的多种方法

《Python使用pip工具实现包自动更新的多种方法》本文深入探讨了使用Python的pip工具实现包自动更新的各种方法和技术,我们将从基础概念开始,逐步介绍手动更新方法、自动化脚本编写、结合CI/C... 目录1. 背景介绍1.1 目的和范围1.2 预期读者1.3 文档结构概述1.4 术语表1.4.1 核