[python][collections] namedtuple 命名元组

关于 collections 模块

python 自带的一些数据类型已经很是实用了,但在一些状况下,原生的数据结构并不能知足咱们的需求。而在 python 中,想从底层定义一种数据类型又特别困难。所以, python 在它的 collections 模块中又为咱们提供了几种新的数据类型,灵活的使用它们将会提高咱们编写程序的效率。python

1. 为何要用命名元组

不少时候,咱们须要用比较规范的形式将数据组织在一块儿,而对于简单的数据,使用结构体就有一些大材小用了。这个时候, namedtuple 这个类就能够很好地帮咱们解决这一个问题。编程

2. 定义元组

命名元组的定义方式是: namedtuple(typename, field_names) ,其中 typename 是这一种命名元组的名字,而 field_names 是元素对应的名称,并且它能够为下面的任意一种形式:bash

  • ['x', 'y']数据结构

  • 'x y'code

  • 'x, y'io

介绍了申明的方法了以后,咱们就拿一个最简单的例子来实战一下。在 python 程序中,咱们常常用到“点”这样的类型,而这种时候命名元组的便捷性就体现出来了。class

from collections import namedtuple
p = namedtuple('Point', ['x', 'y'])

这样,咱们就定义了一种新的命名元组,接下来咱们就可使用它了。效率

3. 使用元组

接下来,咱们用定义好的命名元组建立两个新的元组:import

a = p(1, 2)
b = p(x=3, y=4)
print(a)

能够看到,初始化命名元组时,直接赋值与关键字赋值都是能够的,而这一段程序的输出结果是:变量

Point(x=1, y=2)

前面的 Point ,就是咱们刚刚标记的命名元组名称。这样就说明 ab 这两个变量已是 Point 类型的了。此时,咱们试一下求一下这两个点之间的距离。

dis = lambda a, b : ((a.x - b.x) ** 2 + (a.y - b.y) ** 2) ** 0.5
print(dis(a, b))
2.8284271247461903

能够看到,这个时候咱们就能够经过 a.x 这样的形式访问命名元组中的元素了。固然,咱们仍是能够像以前同样,使用 a[0] 来获取第一个元素。

4. 将一个列表导入到命名元组

有些时候,咱们想将一个列表导入到命名元组中,这个时候咱们就可使用 _make() 方法来完成。

l = [1, 2]
a = p._make(l)
print(a)
Point(x=1, y=2)

有些时候,将列表转化为命名元组,会更有利于数据的处理,所以要灵活使用这一项功能。

5. 修改命名元组的值

标题看上去很使人疑惑--一个元组的值怎么能被修改呢。其实所谓的“修改”,就是新建一个修改后的元组,替换原有的元组,这样至关于间接地完成了元组的修改。而这一个功能能够经过内置方法 _replace() 来实现。

a = p(x=1, y=2)
a._replace(x=3)
print(a)
Point(x=3, y=2)

这样经过内置方法,咱们就能够去“修改”命名元组的值了。

6. 命名元组的嵌套

比方说,我以前定义了一个命名元组叫 Point,而我如今想要定义一个正方形 Square ,它由 x, y, a 组成。那么这个时候,咱们可否套用以前 Point 的定义,去组合出 Square 这个类型呢?

这固然是能够的,当咱们使用命名元组的 _fields 这一个属性时,它将会返回这个元组组成的元素名称。

>>> p._fields
('x', 'y')

而将这个返回值用于定义新命名元组时的参数设定,咱们也就实现了命名元组的嵌套:

sq = namedtuple('Square', p.fields + ('a',))
s = sq(1, 1, 4)
print(s)
Square(x=1, y=1, a=4)

这样咱们就实现了一个正方形的定义。那咱们能不能用另方法,去定义实现一种新的命名元组"矩形" Rectangle ,它由两组 xy 坐标组成呢?

rect = namedtuple('Rectangle', p._fields * 2)
Encountered duplicate field name: 'x'

能够看到,它提示咱们有重复的属性 x ,由于命名元组要求参数惟一,这也是命名元组相较于结构体的一个缺陷。这时咱们只能老老实实的用不一样的变量名了。。。

rect = namedtuple('Rectangle', 'x1 y1 x2 y2')
r = rect(0, 0, 4, 4)
print(r)
Rectangle(x1=0, y1=0, x2=4, y2=4)

结语

正确地使用 namedtuple 可使咱们的代码变得更加直观,而且相较于结构体,它的定义更加的轻量化。不过固然,在某些状况下,咱们仍是须要使用结构体来完成更复杂的操做。所以咱们在编程时应看成出合理的选择,这样才能发挥 python 最大的效率。

相关文章
相关标签/搜索