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中,一切皆对象,而对象都是由类 ...
随机推荐
- Linux shell之数组
引言 在Linux平台上工作,我们经常需要使用shell来编写一些有用.有意义的脚本程序.有时,会经常使用shell数组.那么,shell中的数组是怎么表现的呢,又是怎么定义的呢?接下来逐一的进行讲解 ...
- [转载]GDB十分钟教程
转自:http://blog.csdn.net/liigo/article/details/582231/ GDB十分钟教程 作者: liigo原文链接: http://blog.csdn.net/l ...
- 【字符串排序,技巧!】UVa 10905 - Children’s Game
There are lots of number games for children. These games are pretty easy to play but not so easy to ...
- 【转】ArrayList的toArray,也就是list.toArray[new String[list.size()]];,即List转为数组
[转]ArrayList的toArray ArrayList提供了一个将List转为数组的一个非常方便的方法toArray.toArray有两个重载的方法: 1.list.toArray(); 2.l ...
- Delphi推出Delphi XE4支持IOS开发
Delphi 新推出 Delphi XE4 ,这是一个支持 iOS 应用开发的新版本.Delphi XE4 带来 Embarcadero 全新的 ARM 编译器 下载地址
- C# string.Format格式化时间或货币
1.格式化货币(跟系统的环境有关,中文系统默认格式化人民币,英文系统格式化美元) string.Format("{0:C}",0.2) 结果为:¥0.20 (英文操作系统结果:$0 ...
- php正则失效-最大回溯(pcre.backtrack_limit)/递归限制
有时候,我们觉得,没有什么可以让我们快乐,我们甚至忘记了如何微笑.但是,当我们被一群乐观.欢乐的人包围的时候,他们从内心深处散发出来的欢迎一定会感染你. 这组照片中,你会看到真正的幸福和快乐的面孔,我 ...
- IOS- 最简单的反向传值- block
block 常用于反向传值 声明 返回值类型 (^block)(参数列表) 调用 闭包的名字=^(参数列表){}: 闭包的名字(): 如: void(^aaaaa)(int num,NSString ...
- [jquery]高级篇--获取div子元素
参考: http://zhidao.baidu.com/link?url=IfeQQBn1xMLqWvwdkKbQYJ8mC6ciGi_8M1NYkm6iQ-kXBMX2f2ylN-ckzFLiynn ...
- 393. UTF-8 Validation
393. UTF-8 Validation 这个题很明确,刚开始我以为只能是一个utf,长度大于5的都判断为false,后来才明白题意. 有个小trick,就是长度大于1的时候,判断第一个数字开始1的 ...