Python中的元类MetaClass

news2024/10/7 18:30:46

引言

python中的元类MetaClass:本质也是一个类,但和普通类的用法不同,它可以对类内部的定义(包括类属性和类方法)进行动态的修改。

 换句话说,使用元类的主要目的是为了实现在创建类时,能够动态的改变类中定义的属性或者方法。

1、自定义元类创建类的基本方法

第一步:创建元类,一个类必须继承type才能使其成为一个元类;

第二步:创建类,使用关键词参数metaclass指定创建它的元类。

2、元类的__new__方法

 在类的创建过程中,元类的__new__方法和__init__方法会被先后调用,前者负责创建类,后者负责类的初始化。在实际使用中,大多类的初始化工作都可以放在__new__方法中进行,所以为了代码简洁往往只需要定义__new__方法。 

class FirstMetaClass(type):
    '''
    cls:代表动态修改的类
    name:代表动态修改的类名
    bases:代表被动态修改的类的所有父类
    attr:代表被动态修改的类的所有属性、方法组成的字典
    '''
    def __new__(cls, name, bases, attrs):
        attrs['name'] = 'C语言中文网'
        attrs['say'] = lambda self: print('调用say()实例方法')
        return super().__new__(cls, name, bases, attrs)
# 通过FirstMetaClass元类创建的类,会额外添加name属性和say()方法。

class CLanguage(object, metaclass=FirstMetaClass):
    pass

if __name__ == '__main__':
    clangs = CLanguage()
    print(clangs.name)
    clangs.say()

 

可以看到,在创建类时,通过元类创建的类会调用元类中的__new__方法,从而实现动态修改类属性或者类方法的目的。

3、元类创建API实例---Django ORM 

class ModelMetaClass(type):

    def __new__(cls, name, bases, attrs):
        mappings = dict()
        for k, v in attrs.items():
            # 只处理类中属性值为元组的键值对
            if isinstance(v, tuple):
                print('Found mapping: %s==>%s' % (k, v))
                mappings[k] = v

        # 处理完成后删除属性
        for k in mappings:
            attrs.pop(k)

        attrs["__mappings__"] = mappings
        attrs["__table__"] = name
        # 这里不能用type(name, bases, attrs) 直接返回创建好的类, 不会触发type的__init__方法
        return type.__new__(cls, name, bases, attrs)


class Model(metaclass=ModelMetaClass):
    # uid = ("uid", "int unsigned")
    # name = ("username", "varchar(30)")
    # email = ("email", "varchar(30)")
    # password = ("password", "varchar(30)")

    def __init__(self, **kwargs):
        # 将关键字参数添加到实例属性
        for k, v in kwargs.items():
            setattr(self, k, v)

    def save(self):
        table_name = self.__table__
        field = list()
        args = list()
        for k, v in self.__mappings__.items():
            field.append(v[0])
            arg = getattr(self, k, None)
            # ["12345","""'Michael'""","""'test@orm.org'""","""'my-pwd'"""]
            if isinstance(arg, str):
                args.append("""'{}'""".format(arg))
            else:
                args.append(str(arg))

        sql = "insert into {}({}) values ({})".format(table_name, ",".join(field), ",".join(args))
        print(f"SQL语句: {sql}")


class User(Model):
    uid = ("uid", "int unsigned")
    name = ("username", "varchar(30)")
    email = ("email", "varchar(30)")
    password = ("password", "varchar(30)")


u = User(uid=12345, name="Michael", email="test@orm.org", password="my-pwd")
u.save()

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/795607.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数据库架构设计

数据库架构设计 数据库架构分类 介绍 介绍常见的 四种 数据库架构设计模型: 单库架构、分组架构、分片架构和分组分片架构 ,以及每种架构的 使用场景、存在的问题和对应的解决方案 。 一、数据模型 我们以 “ 用户中心 ” 数据库作为 数据模型 &…

python核心-面向对象-方法相关-补充

class Person:__age 18def __run(self):print("pao")def _Person__run(self):print("xxx")p Person # p._Person__run()print(Person.__dict__) 内置特殊方法 信息格式化操作 # class Person: # def __init__(self, n, a): # self.name n …

深入理解Linux 内核追踪机制

Linux 存在众多 tracing tools,比如 ftrace、perf,他们可用于内核的调试、提高内核的可观测性。众多的工具也意味着繁杂的概念,诸如 tracepoint、trace events、kprobe、eBPF 等,甚至让人搞不清楚他们到底是干什么的。本文尝试理清…

硬件——PCI-E接口

简介 PCI PCI(Peripheral Component Interconnect),外设组件互联标准。 并行方式通信 PCI接口通常是白色的。 PCI接口分为32Bit和64Bit,主流的是32Bit,最大传输速度133MB/s。 适用于网卡、声卡等;现在…

flask中的session介绍

flask中的session介绍 在Flask中,session是一个用于存储特定用户会话数据的字典对象。它在不同请求之间保存数据。它通过在客户端设置一个签名的cookie,将所有的会话数据存储在客户端。以下是如何在Flask应用中使用session的基本步骤: 首先…

Midjourney8种风格极其使用场景(1)

目录 ​编辑 引言 等距动画 场景 分析性绘图 场景 着色书 场景 信息图画 场景 双重曝光 场景 图示性绘画 场景 二维插图 场景 图解式画像 场景 总结: 八种风格箴言: 引言 我相信大家都或多或少玩过Midjourney,但是要形…

Excel“牛人”变现方案参考

有几种方式可以通过Excel技能实现变现: 1. 提供Excel咨询和培训服务:如果你对Excel非常熟悉,你可以提供咨询和培训服务,帮助他人解决Excel使用中的问题或提高他们的Excel技能。 2. 制作和销售Excel模板:你可以根据市…

同步和异步——简单的Demo

一、程序中的同步和异步的区别 在编程中,同步和异步是指代码执行的方式和顺序。 1. 同步(Synchronous): 同步代码按照顺序依次执行,每个操作必须等待前一个操作完成后才能执行。在同步模式下,代码会阻塞&…

部署问题集合(十八)Windows环境下使用两个Tomcat

下载Tomcat Tomcat镜像下载地址:https://mirrors.cnnic.cn/apache/tomcat/进入如下地址:zip的是压缩版,exe是安装版 修改第二个Tomcat配置文件 第一步:编辑conf/server.xml文件,修改三个端口,有些版本改…

信号量SytemV与Posix信号量的介绍与用法

目录 1、信号量介绍 2、信号量SystemV介绍 2.1 信号量函数 2.2 信号量C代码实现 3、信号量Posix介绍 3.1 无名信号量 3.2 有名信号量 1、信号量介绍 信号量是一种计数器,用在多进程、多线程的共享资源访问控制上面,防止多进程、多线程对共享资源的…

win下tomcat部署问题积累

1、win下双击tomcat的start.bat出现闪退 检查环境变量是否配置正确: 1.在已解压的tomcat的bin文件夹下找到startup.bat,右击->编辑。在文件头加入下面两行: SET JAVA_HOMED:\Java\jdk1.6.0_10 (java jdk目录)S…

【C语言进阶】程序环境和预处理

🔥博客主页:小王又困了 📚系列专栏:C语言 🌟人之为学,不日近则日退 ❤️感谢大家点赞👍收藏⭐评论✍️ 目录 一、程序的翻译环境和执行环境 二、详解编译和链接 2.1翻译环境 2.2编译的过…

Centos yum install出现Error: Unable to find a match: epel-release的解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

MySQL基础扎实——MySQL中有哪几种锁

常见锁举例 在MySQL中,常见的锁包括以下几种: 表级锁(Table-level Lock):表级锁是对整张表进行锁定,可以分为两种类型: 共享锁(Shared Lock):也称为读锁&…

Google Earth Engine谷歌地球引擎提取多波段长期反射率数据后绘制折线图并导出为Excel

本文介绍在谷歌地球引擎GEE中,提取多年遥感影像多个不同波段的反射率数据,在GEE内绘制各波段的长时间序列走势曲线图,并将各波段的反射率数据与其对应的成像日期一起导出为.csv文件的方法。 本文是谷歌地球引擎(Google Earth Engi…

Python图像处理【13】使用PIL执行图像降噪

使用PIL执行图像降噪 0. 前言1. 均值滤波器1.1 均值滤波器原理1.2 使用均值滤波器去除椒盐噪声 2. 高斯滤波器2.1 高斯滤波器原理2.2 使用高斯模糊滤波器去除椒盐噪声 3. 中值滤波器3.1 中值滤波器原理3.2 使用中值滤波器去除椒盐噪声 小结系列链接 0. 前言 在本节中&#xff…

MAXENT模型的生物多样性教程

详情点击链接:基于MAXENT模型的生物多样性生境模拟与保护优先区甄选、自然保护区布局优化及未来气候变化下评估中的应用及论文写作 一:生物多样性保护格局与自然保护区格局优化 1.我国生物多样性格局与分布; 2.我国自然保护区格局与分布&…

Emacs之改造搜索文件fd-dired(基于fd命令)(一百二十一)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 人生格言: 人生…

【【51单片机AD转换模块】】

代码是简单的&#xff0c;板子是坏的&#xff0c;电阻是识别不出来的 main.c #include <REGX52.H> #include "delay.h" #include "LCD1602.h" #include "XPT2046.h"unsigned int ADValue;void main(void) {LCD_Init();LCD_ShowString(1,1…

format格式化输出语法详解

hello&#xff0c;这里是Token_w的文章&#xff0c;主要讲解python的基础学习&#xff0c;希望对大家有所帮助 整理不易&#xff0c;感觉还不错的可以点赞收藏评论支持&#xff0c;感谢&#xff01; 使用 % 操作符对各种类型的数据进行格式化输出&#xff0c;这是早期 Python提…