Python中的metaclass
来源:互联网 发布:apache subversion 编辑:程序博客网 时间:2024/06/08 00:44
Python中的metaclass
我们知道,当一个类定义了,那么类其中的成员变量和函数也就确定了。而metaclass就是一种在运行时动态设置成员变量和函数的一种方法
type()函数
type(name, bases, dict)
类名称(name)、父类列表(bases)和 属性字典(dict) “
python中一个类的定义可以通过 class 类名(父类)
来定义,同样可以通过上面的type函数形式定义
>>> class user(object):... user = "user"... key = "key"...>>> print(user)<class '__main__.user'>>>> u = user()>>> u.user'user'>>> u.key'key'
再看使用type定义
>>> user = type("user",(),{"name":"user","key":"123456"})>>> u = user()>>> u.name'user'>>> u.key'123456'
其中可以看到user类中成员函数和变量都是用dict存放的,那么,我们只需要动态的改变dict中的内容就对应修改了这个类的成员变量和函数
metaclass 类
定义一个类,表示用此类或子类的定义的变量是可以改变的
class Field(object): def __init__(self,): pass
再定义几个子类,同样用这些类定义的变量都是可以改变的
class IntegerField(Field): def __init__(self): super(IntegerField, self).__init__()class StringField(Field): def __init__(self): super(StringField, self).__init__()
定义三个成员变量,其中两个是可以改变的
class User(Model): age = 20 name = StringField() sex = IntegerField()
此处到了重点,什么是元类,元类就是创建类的类。也可以说他就是一个类的创建工厂,如 type 函数。
User 中有__metaclass__
这个属性吗?如果有,那么Python会在内存中通过__metaclass__
创建一个名字为User 的类对象。如果Python没有找到__metaclass__
,它会继续在自己的父类Model中寻找__metaclass__
属性,并且尝试以__metaclass__
指定的方法创建一个User 类对象。如果Python在任何一个父类中都找不到__metaclass__
,它也不会就此放弃,而是去模块中搜寻是否有__metaclass__
的指定。如果还是找不到,那就是使用默认的type来创建User
class Model(dict, metaclass=ModelMetaclass): def __init__(self, **kw): super(Model, self).__init__(**kw) def __getattr__(self, key): try: return self[key] except KeyError: raise AttributeError(r"'Model' object has no attribute '%s'" % key) def __setattr__(self, key, value): self[key] = value
注意到模块集成自dict,有__getattr__
和__setattr__
方法,那么只要将任意变量名的成员赋值,就相当于为类添加了成员函数
class ModelMetaclass(type): # __new__方法接受的参数依次是: # 1.当前准备创建的类的对象(cls) # 2.类的名字(name) # 3.类继承的父类集合(bases) # 4.类的方法集合(attrs) def __new__(cls, name, bases, attrs): # 排除Model类本身: if name == 'Model': return type.__new__(cls, name, bases, attrs) # 获取所有的Field和主键名: mappings = dict() fields = [] for k, v in attrs.items(): if isinstance(v, Field): mappings[k] = v # 删除成员变量重新构造 for k in mappings.keys(): attrs.pop(k) return type.__new__(cls, name, bases, attrs)
注意:
其中,attrs.pop(k)
将我们事先定义好的成员变量删除,那么起始状态,其中并没有name和sex字段
由于Model集成自dict,User也继承自dict。之前提到过,类的成员变量和函数都是以dict存放,这样ModelMetaclass类__new__
函数中传入的参数attr就是它自生,那么当我们往Model中添加数据时,相当于给User添加成员变量
u1 = User(name="user",sex=1) #添加了name和sex字段u2 = User(name="user") #只添加了name字段u3 = User(sex=1) #只添加了sex字段
[参考]:https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/0014319106919344c4ef8b1e04c48778bb45796e0335839000
- Python中的metaclass
- python中的metaclass
- Python中的metaclass
- Python中的metaclass
- 【编程语言】python中的metaclass
- Python中的元类(metaclass)
- Python中的元类(metaclass)
- Python中的元类(metaclass)
- python中的元类Metaclass
- python中的元类Metaclass
- Python中的元类(metaclass)
- 深刻理解Python中的元类(metaclass)
- 深刻理解Python中的元类(metaclass)
- 深刻理解Python中的元类(metaclass)
- 深刻理解Python中的元类(metaclass)
- 深刻理解Python中的元类(metaclass)
- 深刻理解Python中的元类(metaclass)
- 深刻理解Python中的元类(metaclass)
- C# WinForm程序退出的方法
- [Struts2 框架学习] 一、Hello,Struts
- Spring框架:启动IOC容器的三种方式
- jar工程install打成包的时候失败
- spring配置error2 AOP事务配置缺少包
- Python中的metaclass
- NYOJ J : CTX学长的找位置游戏
- static、final、static final 用法
- Java 之 Serializable 序列化和反序列化的概念,作用的通俗易懂的解释
- 51nod 1335 子序列翻转
- 设计电路加法实验
- Django复习:视图和模版
- Hi3519V101上移植QT4.8.6
- SDUT-2482