什么是命名元组,我如何使用它们? 什么时候我应该使用命名元组而不是正常的元组,反之亦然? 也有“名单”吗?(即可变命名元组)


关于最后一个问题,请参见Python中是否存在可变命名元组。


当前回答

什么是namedtuple ?

顾名思义,namedtuple是带有name的元组。在标准元组中,我们使用索引访问元素,而namedtuple允许用户为元素定义名称。这是非常方便的,特别是处理csv(逗号分隔值)文件和处理复杂的大型数据集,其中代码因使用索引而变得混乱(不是那么python化)。

如何使用它们?

>>>from collections import namedtuple
>>>saleRecord = namedtuple('saleRecord','shopId saleDate salesAmout totalCustomers')
>>>
>>>
>>>#Assign values to a named tuple 
>>>shop11=saleRecord(11,'2015-01-01',2300,150) 
>>>shop12=saleRecord(shopId=22,saleDate="2015-01-01",saleAmout=1512,totalCustomers=125)

阅读

>>>#Reading as a namedtuple
>>>print("Shop Id =",shop12.shopId)
12
>>>print("Sale Date=",shop12.saleDate)
2015-01-01
>>>print("Sales Amount =",shop12.salesAmount)
1512
>>>print("Total Customers =",shop12.totalCustomers)
125

CSV处理中的有趣场景:

from csv import reader
from collections import namedtuple

saleRecord = namedtuple('saleRecord','shopId saleDate totalSales totalCustomers')
fileHandle = open("salesRecord.csv","r")
csvFieldsList=csv.reader(fileHandle)
for fieldsList in csvFieldsList:
    shopRec = saleRecord._make(fieldsList)
    overAllSales += shopRec.totalSales;

print("Total Sales of The Retail Chain =",overAllSales)

其他回答

命名元组基本上是易于创建的轻量级对象类型。命名元组实例可以使用类似对象的变量解引用或标准元组语法来引用。它们可以类似于struct或其他常见记录类型使用,但它们是不可变的。它们是在Python 2.6和Python 3.0中添加的,尽管在Python 2.4中有一个实现方法。

例如,通常将一个点表示为元组(x, y)。这将导致如下代码:

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

from math import sqrt
line_length = sqrt((pt1[0]-pt2[0])**2 + (pt1[1]-pt2[1])**2)

使用命名元组,它变得更具可读性:

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 = namedtuple('Point', 'x y')
pt1 = Point(1.0, 5.0)
pt2 = Point(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

因此,在任何您认为对象表示法会使代码更python化、更易于阅读的地方,都应该使用命名元组而不是元组。我个人已经开始使用它们来表示非常简单的值类型,特别是在将它们作为参数传递给函数时。它使函数更具可读性,而无需看到元组打包的上下文。

此外,您还可以替换普通的不可变类,这些类没有函数,只有字段。你甚至可以使用你的命名元组类型作为基类:

class Point(namedtuple('Point', 'x y')):
    [...]

然而,与元组一样,命名元组中的属性是不可变的:

>>> Point = namedtuple('Point', 'x y')
>>> pt1 = Point(1.0, 5.0)
>>> pt1.x = 2.0
AttributeError: can't set attribute

如果您希望能够更改值,则需要另一种类型。对于可变记录类型有一个方便的方法,它允许您为属性设置新值。

>>> from rcdtype import *
>>> Point = recordtype('Point', 'x y')
>>> pt1 = Point(1.0, 5.0)
>>> pt1 = Point(1.0, 5.0)
>>> pt1.x = 2.0
>>> print(pt1[0])
    2.0

然而,我不知道有任何形式的“命名列表”可以让你添加新字段。在这种情况下,你可能只需要使用字典。命名元组可以使用pt1._asdict()转换为字典,它返回{'x': 1.0, 'y': 5.0},并且可以使用所有常用的字典函数进行操作。

如前所述,您应该查看文档以获得构建这些示例的更多信息。

其他人都已经回答了,但我想我还有一些东西要补充。

Namedtuple可以直观地视为定义类的快捷方式。

请参阅定义类的繁琐而传统的方法。

class Duck:
    def __init__(self, color, weight):
        self.color = color
        self.weight = weight
red_duck = Duck('red', '10')

    In [50]: red_duck
    Out[50]: <__main__.Duck at 0x1068e4e10>
    In [51]: red_duck.color
    Out[51]: 'red'

至于namedtuple

from collections import namedtuple
Duck = namedtuple('Duck', ['color', 'weight'])
red_duck = Duck('red', '10')

In [54]: red_duck
Out[54]: Duck(color='red', weight='10')
In [55]: red_duck.color
Out[55]: 'red'
  from collections import namedtuple 

他们子类化tuple,并添加一个层来为位置元素分配属性名

'namedtuple'是一个函数,它生成一个继承自“tuple”的新类,但也提供了“命名属性”来访问元组的元素。

生成命名元组类

"namedtuple"是一个类工厂。它需要一些东西来生成类

the class name A sequence of field names we want to assign, in the order of elements in the tuple. Field names can be any valid variable names except that they cannot start with an "underscore". The return value of the call to "namedtuple" will be a class. We need to assign that class to a variable name in our code so we can use it to construct instances. In general, we use the same name as the name of the class that was generated. # Coords is a class Coords = namedtuple('Coords', ['x', 'y']) Now we can create instances of Coords class: pt=Coords(10,20) There are many ways we can provide the list of field names to the namedtuple function. a list of strings namedtuple('Coords',['x','y']) a tuple of strings namedtuple('Coords',('x','y')) a single string with the field names separated by whitespace or commas namedtuple('Coords','x, y'])

实例化命名元组

创建了命名的tuple类之后,可以像实例化普通类一样实例化它们。事实上,生成类的__new__方法使用我们作为参数名提供的字段名。

Coords = namedtuple('Coords', ['x', 'y'])
coord=Coords(10,20) 

访问命名元组中的数据:

由于命名元组继承自元组,我们仍然可以像处理其他元组一样处理它们:通过索引、切片、迭代

Coords = namedtuple('Coords', ['x', 'y'])
coord=Coords(10,20)       isinstance(coord,tuple) --> True # namedtuple is subclass of tuple

x,y=coord  # Unpacking
x=coord[0] # by index
for e in coord:
    print(e)

现在,我们还可以使用字段名访问数据,就像使用类一样。 坐标。x——> 10 坐标。y——> 20 由于namedtuple是由继承自tuple的类生成的,我们可以这样写: 类Coord(元组): .... "coord"是一个元组,因此是不可变的

"rename"关键字参数为namedtuple

字段名不能以下划线开头

  Coords = namedtuple('Coords', ['x', '_y']) # does not work

namedtuple有一个只包含关键字的参数rename(默认为False),它将自动重命名任何无效的字段名。

Coords = namedtuple('Coords', ['x', '_y'], rename=True)

字段名称“x”不会改变,但“_y”将改变为_1。1是字段名的索引。

想象一下这样的场景:您需要更新应用程序,因此希望使用namedTuple存储应用程序的用户。您需要提取列名,但它们对于命名元组无效,并且会抛出异常。在本例中,使用rename=True。

将命名元组值提取到字典中

Coords = namedtuple('Coords', ['x', 'y'])
coord=Coords(10,20)
coord._asdict()
   {'x': 10, 'y': 20}

为什么使用namedtuple

如果你有这样的课程:

class Stock:
    def __init__(self, symbol, year, month, day, open, high, low, close):
        self.symbol = symbol
        self.year = year
        self.month = month
        self.day = day
        self.open = open 
        self.high = high
        self.low = low
        self.close = close

类方法vs元组方法

stock.symbol              stock[0]     
stock.open                stock[4]
stock.close               stock[7]
stock.high – stock.low     stock[5] – stock[6]

如您所见,元组方法是不可读的。集合中的namedtuple函数允许我们创建一个元组,每个字段或属性都有附加的名称。这可以方便地通过“名称”引用元组结构中的数据,而不仅仅依赖于位置。但请记住,元组是不可变的,所以如果你想要可变性,请坚持使用类

因为namedtuple是可迭代的,你可以使用iterable方法。例如,如果你有" coordinates "作为类实例,你不能查找最大坐标是多少,但是使用name -tuple,你可以。

试试这个:

collections.namedtuple()

基本上,命名元组很容易创建,轻量级的对象类型。 它们将元组转换为用于简单任务的方便容器。 使用namedtuples,您不必使用整数索引访问元组的成员。

例子:

代码1:

>>> from collections import namedtuple

>>> Point = namedtuple('Point','x,y')

>>> pt1 = Point(1,2)

>>> pt2 = Point(3,4)

>>> dot_product = ( pt1.x * pt2.x ) +( pt1.y * pt2.y )

>>> print dot_product
11

代码2:

>>> from collections import namedtuple

>>> Car = namedtuple('Car','Price Mileage Colour Class')

>>> xyz = Car(Price = 100000, Mileage = 30, Colour = 'Cyan', Class = 'Y')

>>> print xyz

Car(Price=100000, Mileage=30, Colour='Cyan', Class='Y')
>>> print xyz.Class
Y

另一种使用命名元组的方法(一种新方法)是使用NamedTuple,来自typing package:在NamedTuple中输入提示

让我们用这篇文章中最上面的答案来看看如何使用它。

在使用命名元组之前,代码是这样的:

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

from math import sqrt

line_length = sqrt((pt1[0] - pt2[0])**2 + (pt1[1] - pt2[1])**2)
print(line_length)

现在我们使用命名元组

from typing import NamedTuple

继承NamedTuple类并在新类中定义变量名。Test是类的名称。

class test(NamedTuple):
    x: float
    y: float

从类中创建实例并为它们赋值

pt1 = test(1.0, 5.0)   # x is 1.0, and y is 5.0. The order matters
pt2 = test(2.5, 1.5)

使用实例中的变量进行计算

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