什么是命名元组,我如何使用它们? 什么时候我应该使用命名元组而不是正常的元组,反之亦然? 也有“名单”吗?(即可变命名元组)
关于最后一个问题,请参见Python中是否存在可变命名元组。
什么是命名元组,我如何使用它们? 什么时候我应该使用命名元组而不是正常的元组,反之亦然? 也有“名单”吗?(即可变命名元组)
关于最后一个问题,请参见Python中是否存在可变命名元组。
当前回答
试试这个:
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是一个用于创建元组类的工厂函数。通过这个类,我们还可以创建可按名称调用的元组。
import collections
#Create a namedtuple class with names "a" "b" "c"
Row = collections.namedtuple("Row", ["a", "b", "c"])
row = Row(a=1,b=2,c=3) #Make a namedtuple from the Row class we created
print row #Prints: Row(a=1, b=2, c=3)
print row.a #Prints: 1
print row[0] #Prints: 1
row = Row._make([2, 3, 4]) #Make a namedtuple from a list of values
print row #Prints: Row(a=2, b=3, c=4)
命名元组基本上是易于创建的轻量级对象类型。命名元组实例可以使用类似对象的变量解引用或标准元组语法来引用。它们可以类似于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'
命名元组是一个很好的特性,它们是数据的完美容器。当你必须“存储”数据时,你会使用元组或字典,比如:
user = dict(name="John", age=20)
or:
user = ("John", 20)
字典方法是压倒性的,因为字典是可变的,比元组慢。另一方面,元组是不可变和轻量级的,但是对于数据字段中的大量条目缺乏可读性。
命名元组是这两种方法的完美折衷,它们具有很高的可读性、轻量级性和不可变性(而且它们是多态的!)
命名元组允许与这样检查版本的代码向后兼容
>>> sys.version_info[0:2]
(3, 1)
同时通过使用此语法允许未来的代码更加显式
>>> sys.version_info.major
3
>>> sys.version_info.minor
1