前言
在Python中,我们使用元组往往是直接按其索引进行操作的。比如一个c元组(1,2,3),那么获取2值c[1]。对于简单的数据而言,这种操作没有什么问题。
但数据结构的重点,就是在实际的需求多样化中,找到最符合的数据结构进行数据的操作变更。而当元组tuple有大量数据时,记住各个值对应哪个索引,显然是不可能的。而namedtuple除了为各个成员指定数值索引外,还为其指定了名字。
本篇,将详细介绍namedtuple的使用方式以及优点。
初识namedtuple
与常规的元组一样,namedtuple实例在内存使用方面同样很高效,因为它们没有每一个实例的字典。各种namedtuple都由自己的类表示,这个类使用namedtuple()工厂函数来创建。参数就是新类名和一个包含元素名的字符串。
具体示例如下:
import collections Person = collections.namedtuple('Person', 'name age') lyj = Person(name="Li YuanJing", age=28) fxy = Person(name='Feng XinYao', age=30) hf = Person(name='He Fan', age=28) for person in [lyj, fxy, hf]: print(person.name, person.age)
运行之后,效果如下:
需要注意的是,在python中常规元组是不可修改的,namedtuple也一样。这个限制允许tuple实例具有一致的散列值,这使得可以把它们用作字典中的键并包含在集合中。
非法字段处理
在实际的编程中,我们变量的起名一般都会与编程语言的关键字岔开。因为取一个和编程语言一样的关键字名称,会被系统提示报错。
而namedtuple也一样,不过我们可以进行规避。首先,我们先来看一看使用关键字会有什么效果:
import collections Person = collections.namedtuple('Person', 'name age class')
运行之后,效果如下:
如上面代码所示,我们使用了关键字class,运行程序会直接报ValueError错误。那么,namedtuple是如何规避这种错误的呢?不妨我们在来看一段代码。
import collections Person = collections.namedtuple('Person', 'name age class', rename=True)
通过第3个参数:rename,我们可以防止namedtuple报错。但是哪怕这样能运行。也不能直接赋值。但可以通过别名赋值,具体可以看下面的代码。
需要注意的是,rename并不仅仅只是用来规避错误的,而是当有重复的属性时,依旧可以赋值。具体代码如下:
import collections Person = collections.namedtuple('Person', 'name age age', rename=True) print(Person._fields) a = Person(name='tom', age=25, _2=255) print(a)
class属性与重复属性同理。
_asdict()
对于namedtuple来说,创建的实例是不允许进行更改的。那么,如果后续的处理需要进行更改怎么办?这里,我们可以直接把namedtuple转换为OrderedDict进行处理。
具体代码如下:
import collections Person = collections.namedtuple('Person', 'name age age', rename=True) a = Person(name='tom', age=25, _2=255) print(a) b = a._asdict() print(b) b['name'] = '123' print(b)
运行之后,效果如下:
_replace()
namedtuple还有一个函数,就是_replace()。从前面的字符串处理中,我们可以大致猜出来,这个函数就是替换值得。但是前面说了namedtuple是不能更改的。那这个函数的意义是什么?
其实,_replace()函数虽然看起来替换了原来的值,但它只是返回了一个新的namedtuple实例,并未对之前的实例造成任何修改。我们来看一段代码就清楚了:
import collections Person = collections.namedtuple('Person', 'name age') a = Person(name='tom', age=25) print("原始a值") print(a) print("------------------") b = a._replace(name='jerry') print("replace后的ab值") print(a) print(b)
运行之后,效果如下: