[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 最大的效率。

相關文章
相關標籤/搜索