python当中的metaclass使用
python当中的metaclass
简单介绍
- python中对象也是类,类作为一种特别的对象存在,特别之处就在于可以作为一个模板来生成对象(所有的类都是),暂且把python中的类称为类对象,类对象使用class定义。
- 除了class定义, 我们也可以用type来创建一个类。
type(class_name, base_class, attrs)
# example
NewClass = type("NewCls", (), {"name":"bob"})
a = NewClass()
a.name
我们用type成功生成了一个类,他的意义在于,我可以在程序运行的过程中,使用代码动态的去定义一个类(*区别于那种传统的先用class定义完你用的类,然后实例化使用的方式*)
既然使用type可以动态创建类,代码种可能就会存在这样一种情况
cls = {"Ncls":{"bases":(), "attrs":{}}} (格式举例) cls_list = [] for k, v in cls_dict: new_cls = type(k, v["bases"], v["attrs"]) cls_list.append(new_lcs)
这里使用type,将一个字典或者列表,动态的转化生成一个类数组
- metaclasss有什么用?type可以创建类,如果存在一个方法,返回一个type动态创建的类,在使用class定义类的时候,把这个方法赋值给metaclass,就可以实现动态的改变class的定义。代码说明一切,这里用py3语法。
def upper_attr(class_name, class_parents, class_attr):attrs = ((name, value)for name, value in class_attr.items() if not name.startswith('__'))uppercase_attrs = dict((name.upper(), value) for name, value in attrs)return type(class_name, class_parents, uppercase_attrs)class NewCls(metaclass=upper_attr):name = "lanix"sex = "male"
NewCls.NAME # lanix
NewCls.name # AttributeError: type object 'NewCls' has no attribute 'name'
很明显,类定义时通过一个metaclass可以把定义的attrs中的属性key,全部变为大写, metaclass除了可以接受一个函数,也可以介绍一个type作为基类的类。类如
class UpperAttrMetaClass(type):def __new__(mcs, class_name, class_parents, class_attr):attrs = ((name, value) for name, value in class_attr.items() if not name.startswith('__'))uppercase_attrs = dict((name.upper(), value) for name, value in attrs)return super(UpperAttrMetaClass, mcs).__new__(mcs, class_name, class_parents, uppercase_attrs)class NewCls(metaclass=UpperAttrMetaClass):name = "lanix"sex = "male"
两者可以实现同样的效果
py2/3版本中的差别。网上搜索到的很多文章都是错的,这真让我崩溃
在py2中, 使用元类(metaclass)可以这么写, 很多介绍metaclass的文章都是这样介绍的,而且当__metaclass__ = MyMetaClass 跟类定义同级别时,会成为所有同级别的类的元类。
class NewClass:__metaclass__ = MyMetaClass
但是在py3版本中, 并不支持__metaclass__的写法,应该
class NewClass(metaclass=MyMetaClass):pass
一个简单的使用案例
比如在游戏开发中,要定义一个角色,它大概有几种动作(状态
最简单的方式可以
class BadMan:def __init__(self, name):self.name = nameself.state = ''def run(self):print(f'{self.name} is runing!')self.state = "run"def fight(self):print(f'{self.name} is fighting')self.state = "fight"b = BadMan("bob")
b.run()
定义都是固定不变的,不够灵活 ,也不够优雅。这里有一个使用metaclass的例子, 可以使用metaclass写一个fsm。
class Action(object):def __init__(self, act_desc):self.desc = act_descclass ManMeta(type):def __new__(cls, name, bases, attrs):actives = {}for k, v in attrs.items():if isinstance(v, Action):cls.add_action(actives, k, v)attrs.update(actives)return type.__new__(cls, name, bases, attrs)@classmethoddef add_action(cls, action_dict, active_name, action_obj):def active(self):self.state = active_nameprint(action_obj.desc)action_dict[active_name] = activeclass Hero(object, metaclass=ManMeta):walk = Action("from on place to another")fight = Action("use weapon to fight")die = Action("your hero is dying now")sleep = Action("fall asleep")def __init__(self):self.state = ""
这里首先定义了一个Active动作类,用来描述各种动作,
随后定义了一个metaclass,并使用这个metaclass 改变了Hero的创建过程,Hero.walk 定义中是一个 Action 实例,在ManMeta中,对这个walk这个属性进行了修改,变为一个类方法的定义函数,经过这一步神奇的转换之后。
z = Hero()
z.fight() # use weapon to fight
z.state # 'fight'
(给Action对象添加一个__call__(self) 也可以实现fight()调用,这里为了解释metaclass, 我们并不关心这些)
metaclass最成功的案例可以百度python orm 实现,metaclass最重要的是提供了一种灵活的类定义的方式。
python当中的metaclass使用相关推荐
- python编译器怎么运行不在路径中的py文件_对python当中不在本路径的py文件的引用详解...
众所周知,如果py文件不在当前路径,那么就不能import,因此,本文介绍如下两种有效的方法: 方法1: 修改环境变量,在~/.bashrc里面进行修改,然后source ~/.bashrc 方法2: ...
- python提供了两种基本的数值类型_python数据分析(一) python当中的数据类型--数字和常用函数...
python当中内置了多种数据类型,了解python内置的基本数据类型,有助于进行进行数据处理.第一篇我们将介绍python当中的数字. 我们将介绍每一种数字类型,他们适用的操作符,以及用于处理的内建 ...
- 超详细,Python当中的pip常用命令大全
相信对于大多数熟悉Python的人来说,一定都听说并且使用过pip这个工具,但是对它的了解可能还不一定是非常的透彻,今天小编就来为大家介绍10个使用pip的小技巧,相信对大家以后管理和使用Python ...
- Python当中reverse()函数
Hello大家好,今天我想和大家分享一下Python当中的reverse()函数 reverse()函数顾名思义就是反转的意思,但是我们要注意反转的内容只能是python当中的列表!千万不要忘记了.例 ...
- 关于在Python当中汉字日期的转换
前几天在做项目的时候遇到了一个关于日期当中汉字转换的问题.平时系统获取的时间都是阿拉伯数字,比如在代码中输入下面的语句: print (datetime.datetime.now().year) 得到 ...
- 超详细!Python当中的pip常用命令大全!
点击上方"菜鸟学Python",选择"星标"公众号 超级无敌干货,第一时间送达!!! 大家好,我是菜鸟哥. 相信对于大多数熟悉Python的人来说,一定都听说并 ...
- Python当中大小写字母与数字的转换 chr()函数,ord()函数,以及ascii_lowercase和ascii_uppercase
Hello大家好,今天我想和大家分享一下在Python当中进行大小写字母与数字的转换: 如果大家想将数字转换成ascii码的话,就使用chr()函数就行,反之的话可以使用ord函数,例如: a = 9 ...
- 如果你是第一次接触Python当中的面向对象,请点击进来。
2018年7月29日15:49:49 今天有时间写一篇关于Python面向对象入门的文章,其实面向对象是不属于某一门编程语言的,而是一种编程思想,如果你是第一次接触面向对象,你需要弄懂下面几个问题: ...
- python——type()、metaclass元类和精简ORM框架
1.type()函数 #type()函数既可以返回一个对象的类型,又可以创建出新的类型, # 比如,我们可以通过type()函数创建出Hello类,而无需通过class Hello(object).. ...
最新文章
- java rabbitmq 绑定_RabbitMQ:交换,队列和绑定 - 谁设置了什么?
- PHP框架 one 1.6.0 发布
- data transformation python_Python数据分析(方睿)
- python 写linux mysql_(linux)python之mysql数据库操作环境搭建
- 初谈Git(本机克隆项目远程仓库)
- Windows Azure 真实案例:CCH 财政服务独立软件开发商(ISV)通过托管服务获得了灵活性并节省成本...
- 前端学习(2655):vue2中用ref实现计算器
- java swing进度条_Java Swing创建自定义闪屏:在闪屏上添加Swing进度条控件(转)
- 金融行业 | 电子银行系统性能优化解决方案
- 机器学习之保存与加载.pickle模型文件
- 听说大家想补补算法和数据结构,给大家推荐一个GitHub 15k星的图文版开源项目...
- 磁盘不见了只剩一个c盘_教你如何处理只剩一个C盘
- 局域网ip扫描工具_中科院网络工程师网络安全视频教程10端口扫描
- spring基础知识(IOC、DI、AOP)
- 化妆品护肤DiY的广告界面 简单的jquery 图片无缝滚动
- 报错笔记-[error] 1615#0: *14 open() “/usr/local/nginx/html/course/zk.jpg“ failed (2: No such file or dir
- POJ 2395 Out of Hay 最小生成树 Kruskal
- 基于vs实现的socket—udp图片传送实例详解
- 论从容自信---张含韵和涛声依旧有感
- 计算机专业面向的职业,职业面向及职业能力要求
热门文章
- Java实现虾米音乐免虾币下载
- 不用摄像头和激光雷达,四足机器人「凭感觉」越野:ANYmal登上Science子刊封面...
- python实战-JSON形式爬虫-批量爬取图片并下载
- 个人目标日历定制制作小工具微信小程序(含源码)
- 实训程序:用户登陆注册,实现宠物的领养
- “i卫星”——行星中的数字编码
- 求解一个数的立方根(想不懂都难)
- Word或Excel 转Pdf 工具类(License 去水印)
- 用lm_sensor来看你的主板和CPU的温度
- Inferring temporal motifs for travel pattern analysis using large scale smart card data