什么是命名元组,我如何使用它们? 什么时候我应该使用命名元组而不是正常的元组,反之亦然? 也有“名单”吗?(即可变命名元组)
关于最后一个问题,请参见Python中是否存在可变命名元组。
什么是命名元组,我如何使用它们? 什么时候我应该使用命名元组而不是正常的元组,反之亦然? 也有“名单”吗?(即可变命名元组)
关于最后一个问题,请参见Python中是否存在可变命名元组。
当前回答
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,你可以。
其他回答
命名元组允许与这样检查版本的代码向后兼容
>>> sys.version_info[0:2]
(3, 1)
同时通过使用此语法允许未来的代码更加显式
>>> sys.version_info.major
3
>>> sys.version_info.minor
1
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},并且可以使用所有常用的字典函数进行操作。
如前所述,您应该查看文档以获得构建这些示例的更多信息。
在Python里面有一个很好的使用容器叫做命名元组,它可以用来创建一个类的定义,并具有原始元组的所有功能。
使用命名的tuple将直接应用到默认的类模板来生成一个简单的类,这种方法允许大量的代码来提高可读性,并且在定义类时也非常方便。
其他人都已经回答了,但我想我还有一些东西要补充。
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'