Python的元类的用法
元类介绍
type可以直接生成类(class),但也可以先生成元类(metaclass),再使用元类批量定制类(class)
使用 class 创建类
class Hello():def say(self, name='world'):print('Hello, %s' % name) h = Hello()h.say()
使用 type 直接创建
def say(self, name='world'):print("Hello, %s" % name)Hello = type('Hello', (object, ), dict(say_hello=say))h = Hello()h.say()
先生成元类 metaclass,再批量创建
# 传入typeclass SayMetaClass(type):# 传入 类名称、父类、属性def __new__(cls, name, bases, attrs):# 添加属性 attrs['say_'+name] = lambda self,value,saying=name: print(saying+','+value+'!')# 传承三大:类名称、父类、属性return type.__new__(cls, name, bases, attrs)# 创建类class Hello(object, metaclass=SayMetaClass):pass# 创建实列hello = Hello()# 调用实例方法hello.say_Hello('world!') # Hello, world! 类名 + 传入的参数class NiHao(object, metaclass=SayMetacalss):passn = NiHao()n.say_NiHao("中国") # NiHao, 中国!
元类的应用
参考文章 快速掌握元类
ORM 对象关系映射
class Field(object):def __init__(self, name, column_type):self.name = nameself.column_type = column_typedef __str__(self):return '<%s: %s>' % (self.__class__.__name__, self.name)class StringField(Field):def __init__(self, name):super().__init__(name, 'varchar(100)')class IntegerField(Field):def __init__(self, name):super().__init__(name, 'bigint')class ModelMetaClass(type):"""元类""""""创建一个新的字典mapping将每一个类的属性,通过.items()遍历其键值对。如果值是Field类,则打印键值,并将这一对键值绑定到mapping字典上。将刚刚传入值为Field类的属性删除。创建一个专门的__mappings__属性,保存字典mapping。创建一个专门的__table__属性,保存传入的类的名称。"""def __new__(cls, name, bases, attrs):if name == 'Model':return type.__new__(cls, name, bases, attrs)print('Found model: %s' % name)mappings = dict()for k, v in attrs.items():if isinstance(v, Field):print('Found mapping: %s ==> %s' % (k, v))mappings[k] = vfor k in mappings.keys():attrs.pop(k)attrs["__mappings__"] = mappingsattrs["__table__"] = namereturn type.__new__(cls, name, bases, attrs)class Model(dict, metaclass=ModelMetaClass):"""创建 Modle 来自于元类"""def __init__(self, **kwargs):super().__init__(**kwargs)def __getattr__(self, key):try:return self[key]except KeyError:raise AttributeError("'Model' object has no attribute '%s'" % key)def __setattr__(self, key, value):self[key] = valuedef save(self):"""模拟 sql 语句"""fields = []args = []for k, v in self.__mappings__.items():fields.append(v.name)args.append(getattr(self, k, None))sql = 'insert into %s (%s) values (%s)' % (self.__table__, ','.join(fields), ','.join(str(i) for i in args))print("SQL: %s" % sql)print("Args: %s" % str(args))class User(Model):"""创建子类""""""id= IntegerField(‘id’)就会自动解析为:Model.__setattr__(self, ‘id’, IntegerField(‘id’))因为IntergerField(‘id’)是Field的子类的实例,自动触发元类的__new__,所以将IntergerField(‘id’)存入__mappings__并删除这个键值对"""id = IntegerField('id')name = StringField('username')email = StringField('email')password = StringField('password')"""实例化过程中先调用Model.__setattr__,将键值载入私有对象然后调用元类的“天赋”,ModelMetaclass._new_,将Model中的私有对象,只要是Field的实例,都自动存入u.__mappings__"""# 实例化 Useru = User(id=12345, name='Batman', email='12343@qq.com', password='qwerqwer')u.save()
Python的元类的用法相关推荐
- Python 的元类设计起源自哪里?
△点击上方"Python猫"关注 ,回复"1"领取电子书 一个元老级的 Python 核心开发者曾建议我们( 点击阅读),应该广泛学习其它编程语言的优秀特性,从 ...
- Python之元类ORM
1. 什么是元类 在Python中一切皆对象,类也是一个对象,实例对象由类创建出来的,类是由元类创建出来的.简而言之,用来创建类的类就叫元类(metaclass). 函数type其实就是一个元类,ty ...
- python 用元类 type 实现对数据库的ORM 映射
python 实现对数据库的ORM 映射 如果使用pymysql 操作数据库 不借助框架的话,频繁写sql语句, 的确比较麻烦 这里借助 type 元类 对 数据表类实现了 与mysql之间的 映射 ...
- Python使用元类约束派生类中必须实现指定的成员
推荐图书: <Python程序设计(第3版)>,(ISBN:978-7-302-55083-9),董付国,清华大学出版社,2020年6月第1次印刷,2021年12月第11次印刷,山东省一流 ...
- python元类是什么_谈谈Python中元类Metaclass(一):什么是元类
简单的讲,元类创建了Python中所有的对象. 我们说Python是一种动态语言,而动态语言和静态语言最大的不同,就是函数和类不是编译时定义的,而是运行时动态创建的. 比方说我们要定义一个HelloW ...
- python的元类与类继承的区别
类的继承,主要涉及 类之间关系. 元类metaclass,某种意思上可以理解为类的父类:类是元类的实例. 第一:type函数创建类 在python中,类也是对象.既然是类是对象,必然有个存在生成它 ...
- Python 的元类问题
一.元类 元类 元类就是类的类,python中函数type实际上是一个元类.type就是Python在背后默认用来创建所有类的元类.Python中所有的东西--都是对象. ...
- python设计一个长方形类_类设计模式python学习~元类
废话就不多说了,开始... 元类是类的模版,在类的层次上标准类的行为. 面下用使元类现实单例设计模式(设计模式九 采取的是另一种方法): from warnings import * 每日一道理 坚持 ...
- python元类的使用_python中元类用法实例
本文实例讲述了python中元类用法,分享给大家供大家参考.具体方法分析如下: 1.元类(metaclass)是用来创建类的类 2.type(object):返回一个对象的类型,与object.__c ...
最新文章
- 对一种自制乐器进行音高修正和音色分析
- C#基础笔记(第九天)
- .NET一个线程更新另一个线程的UI(两种实现方法及若干简化)
- tf.assign()函数简单解释
- 你必须知道的23个最有用的Elasticseaerch检索技巧
- editor多功能文本框在有些计算机上不能正常加载,解决方法,本人用的是把js调用方法放到body/body后面)...
- tomcat启动报错The JRE could not be found.Edit the server and change the JRE location
- Hello Blazor:(1)像ASP.NET WebForm一样写代码
- Oracle关联查询-数据类型不一致问题 ORA-01722: 无效数字
- 对文本文件的各操作(一)
- Vue3+CLI4 使用Element-ui
- php104.tmp,首页-kaka窝论坛-综合管理-细说PHP-kaka窝 - Powered by Discuz!
- 架构之:serverless架构
- 【EasyUse】一键式检索框-界面美化参考。MFC自绘对话框加图和Button
- PredRNN++: Towards A Resolution of the Deep-in-Time Dilemma in Spatiotemporal Predictive Learning
- Sorry, you have been blocked !vultr 又被 openai 屏蔽了,只能换个 vps 了
- oracle 里面declare怎么用啊
- pc端常用电脑屏幕 媒体查询尺寸
- 深入解析云原生网络抖动引起的性能问题 @龙蜥社区eBPF SIG
- 三维高清vR展示模型的应用及优势