越來越簡單的資料類定義:named tuple

songofhawk發表於2022-01-15

說來慚愧,用python也挺久了,第一次發現namedtuple這麼個好東西。先上程式碼:

from collections import namedtuple
Point = namedtuple('Point', ['x', 'y'])
pt1 = Point(1.0, 5.0)
pt2 = Point(2.5, 1.5)

from math import sqrt
line_length = sqrt((pt1.x-pt2.x)**2 + (pt1.y-pt2.y)**2)

是不是很有趣?Point就像一個定義過x和y屬性的類一樣,可以直接建立例項,而所有例項都可以用.x,.y的形式訪問其屬性,這可比直接定義類要省事多了:

class Point:
    def __init__(self, x: float, y: float):
        self.x = x
        self.y = y


pt1 = Point(1.0, 5.0)
pt2 = Point(2.5, 1.5)

from math import sqrt

line_length = sqrt((pt1.x - pt2.x) ** 2 + (pt1.y - pt2.y) ** 2)

顯然,也比用原始的tuple可讀性要好:

pt1 = (1.0, 5.0)
pt2 = (2.5, 1.5)

from math import sqrt
# use index referencing
line_length = sqrt((pt1[0]-pt2[0])**2 + (pt1[1]-pt2[1])**2)
 # use tuple unpacking
x1, y1 = pt1

這還只有兩個成員,要是再多一點,各種數字編號就能把人繞暈了。

所以namedtuple,就是一個基於tuple實現的,建立資料類的快捷方式,讓我們可以快速方便地定義資料結構。當然,它也有一個明顯的缺點:既然底層用tuple實現,就是不可能更改的(immutable),所以pt1.x = 7這樣的語句顯然會報錯。

如果想要一個mutable的快捷資料類,可以用pyrecord:

from pyrecord import Record

Point = Record.create_type('Point', 'x', 'y')
pt1 = Point(1.0, 5.0)
pt2 = Point(2.5, 1.5)

from math import sqrt

line_length = sqrt((pt1.x - pt2.x) ** 2 + (pt1.y - pt2.y) ** 2)

pt1.x = 3.6
new_length = sqrt((pt1.x - pt2.x) ** 2 + (pt1.y - pt2.y) ** 2)

相關文章