Python元类实践--自己定义一个和collections中一样的namedtuple
大家可能很熟悉在collections模块中有一个很好用的扩展数据类型-namedtuple。
如果你还不知道这个类型,那么请翻看标准手册。
我利用元类轻松定义一个namedtuple。
先把代码贴上,满足心急的朋友。
def myNamedTuple(tuple_name, attrs_str):
attrs_set = set(attrs_str.split(' '))
def __init__(self, attrs): #我们将来实例初始化的时候需要调用的方法。
for key, value in zip(attrs_set, set(attrs)):
self.__dict__[key]=value
def __str__(self): #这个只是方便打印用的。
values = [str(x) for x in self.__dict__.values()]
return tuple_name+'(' + ', '.join(values) + ')'
def to_dict(self): #提供一个to_dict()方法,用来把我们的命名元组转为字典。
return self.__dict__
#调用type来建立类。
#第二个参数指定其继承自元组。
#第三个参数指定我们需要存入的属性名(也就是__dict__的键名,然后就是上面定义的方法。
return type(tuple_name, (tuple,),{'attr_keys':attrs_set,'__init__':__init__,'__str__':__str__,'to_dict':to_dict})
if __name__=='__main__':
Point = myNamedTuple('Point','x y')
p = Point([1,2]) #目前我们的参数只能传入一个,否则报错,这是和namedtuple之间的差别。
print(p)
print(type(Point),p, sep='\n')
print(p.x,'---',p.y)
print(p[0],p[1])
print(p.to_dict)
p +=(4,) #此时已经变成了普通的tuple了。内置的namedtuple也是一样。
print(type(Point),p, sep='\n')
实现方法
其实,Python的内部也是创建了一个继承自tuple的类。
>>> from collections import namedtuple
>>> Rectangle=namedtuple('Rectangle', 'height width')
>>> r = Rectangle(3,4)
>>> type(r)
<class '__main__.Rectangle'>
建立一个列表用来存储所有需要存入的健。在将来实例化调用__init__
方法的时候,我们再来建立实例的__dict__
属性字典。
至于取值,那么就是类调用实例的__dict__
了。
如果看不明白的,请先看我关于元类介绍的那一讲。
改进
由于我们的类继承自元组,而元组默认只能传入一个可迭代对象。
那么我们修改一下原来的代码,让我们的myNamedTuple也可以像namedtuple一样可以接受多个参数。
def myNamedTuple(tuple_name, attrs_str):
class Meta(type): #定义一个元类,采用`__call__`方法来拦截类的实例化,在实例化之前我们先把位置参数全部转入一个叫args的元组中,然后在调用type的`__call__`方法,从而把刚才的元组传进去,这样就只有一个参数了,从而无论你传入多少个位置参数,在这个步骤之后,只会出现一个参数了,成功!
def __call__(self, *args):
return type.__call__(self, args)
attrs_set = set(attrs_str.split(' '))
def __init__(self, args):
for key, value in zip(attrs_set, set(args)):
self.__dict__[key]=value
def __str__(self):
values = [str(x) for x in self.__dict__.values()]
return tuple_name+'(' + ', '.join(values) + ')'
def to_dict(self):
return self.__dict__
return Meta(tuple_name, (tuple,),{'attr_keys':attrs_set,'__init__':__init__,'__str__':__str__,'to_dict':to_dict})
if __name__=='__main__':
Point = myNamedTuple('Point','x y')
print(Point)
p = Point(1,2) #多个参数成功调用....
print(p)
print(type(Point),p, sep='\n')
print(p.x,'---',p.y)
print(p[0],p[1])
print(p.to_dict)
p +=(4,) #此时已经变成了普通的tuple了。
print(type(Point),p, sep='\n')
如果有什么不懂的,请留言。
如果这个例子通了,那么collections中的其他数据类型是不是也是一样的道理呢?
Python元类实践--自己定义一个和collections中一样的namedtuple的更多相关文章
- Python 元类使用讲解
我要一大群的类都具有一种特点,我怎么给他们加上呢?模板嘛,我从这个模板创建一群类不就OK了?那就需要元类了. 定义一个元类(就是一个类的模板!莫多想,还要记住这是类级别的,不是对象级别的!):代码如下 ...
- Python进阶丨如何创建你的第一个Python元类?
摘要:通过本文,将深入讨论Python元类,其属性,如何以及何时在Python中使用元类. Python元类设置类的行为和规则.元类有助于修改类的实例,并且相当复杂,是Python编程的高级功能之一. ...
- python元类理解2
恩,对元类理解又有新的收获,其实类似于装饰器,只不过装饰器是修饰函数,元类用来定制一个类. 代码如下,这是一个使用了函数做元类传递给类: input: def upper_attr(class_nam ...
- python元类:type和metaclass
python元类:type和metaclass python中一切皆对象,所以类本身也是对象.类有创建对象的能力,那谁来创建类的呢?答案是type. 1.用tpye函数创建一个类 class A(ob ...
- python元类深入理解
1.python 中的类 在python中,类也是一个对象,只不过这个对象拥有生成实例的能力,我们一般使用class XXX来定义一个类,在python解释器执行到这个地方的时候会自动创建出这个对象, ...
- [TimLinux] Python 元类
1. type函数 name = "This is a string" print(type(name)) # <class 'str'> print("*& ...
- python 元类理解
原文来自:https://segmentfault.com/a/1190000011447445 学懂元类,你只需要知道两句话: 道生一,一生二,二生三,三生万物 我是谁?我从哪来里?我要到哪里去? ...
- Python元类之由浅入深
前言 元类属于python面向对象编程的深层次的魔法,非常重要,它使我们可以更好的掌控类从创建到消亡的整个生命周期过程.很多框架的源码中都使用到了元类.例如 Django Framework 中的 ...
- Python 元类的基本介绍及使用
一.什么是元类 二.如何使用元类 (一)不依赖class关键字创建一个自定义类 (二)自定义元类控制类的产生 (三)自定义元类控制类的调用 一.什么是元类 在python中,一切皆对象,而对象都是由类 ...
随机推荐
- mysql:慢查询日志slow_query_log
1.慢查询日志:当查询超过一定的时间没有返回结果的时候,才会记录到慢查询日志中.默认不开启.采样的时候手工开启.可以帮助DBA找出执行慢的SQL语句 2.常用的参数详解: 注意:修改以下参数,需要重新 ...
- CentOS7安装和配置FTP
1. 安装vsftpd #安装vsftpd yum install -y vsftpd #设置开机启动 systemctl enable vsftpd.service # 重启 service vsf ...
- 分布式 ES 操作流程解析
概念解析 CURD 操作 CURD 操作都是针对具体的某个或某些文档的操作,每个文档的 routing 都是确认的,所以其所在分片也是可以事先确定的.该过程对应 ES 的 Document API. ...
- cgi表单的处理
在HTML中,当客户填写了表单,并按下了发送(submit)按钮后,表单的内容被发送 到了服务器端,一般的,这时就需要有一个服务器端脚本来对表单的内容进行一些处理, 或者是把它们保存起来,或者是按内容 ...
- try{return} finally
今天去逛论坛 时发现了一个很有趣的问题: 谁能给我我解释一下这段程序的结果为什么是:2.而不是:3? 代码如下: class Test { public int aaa() { int x = 1; ...
- 多个DIV让float:left属性,最后一个DIV填满剩余的部分
<DIV style="border:1px solid red; overflow:hidden;zoom:1;"> <DIV style='floa ...
- Android IntentService使用
因为多数启动服务不必同时处理多个请求(在多线程情景下会很危险),所以使用IntentService类实现服务是很好的选择.本经验将通过继承IntentService输出当前时间教大家如何使用Inten ...
- Error:(6, 0) No such property: outputDir for class: org.gradle.api.internal.project.DefaultProject_Decorated
在学习greenDao过程中build.gradle文件中出现这个错误,找了半天不知道为什么.代码我是在git上下载的Demo,按理说应该是没问题的.到最后发现缺少了一个关键字Def // 这样有问题 ...
- EF架构~过滤导航属性等,拼接SQL字符串
拼接T-SQL串,并使它具有通用性 好处:与服务器建立一次连接,给服务器发一条SQL命令,即可实现 代码如下: 1 /// <summary> 2 /// 构建Insert语句串 3 // ...
- popen pclose 不等待命令执行完毕
$handle = popen("start D:\\test.bat", "r"); //exec("start D:\\test.bat" ...