import collections
#Create a namedtuple class with names "a" "b" "c"
Row = collections.namedtuple("Row", ["a", "b", "c"], verbose=False, rename=False)
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)
from collections import Sequence
class MutableTuple(Sequence):
"""Abstract Base Class for objects that work like mutable
namedtuples. Subclass and define your named fields with
__slots__ and away you go.
"""
__slots__ = ()
def __init__(self, *args):
for slot, arg in zip(self.__slots__, args):
setattr(self, slot, arg)
def __repr__(self):
return type(self).__name__ + repr(tuple(self))
# more direct __iter__ than Sequence's
def __iter__(self):
for name in self.__slots__:
yield getattr(self, name)
# Sequence requires __getitem__ & __len__:
def __getitem__(self, index):
return getattr(self, self.__slots__[index])
def __len__(self):
return len(self.__slots__)
使用时,只需子类化并定义__slots__:
class Student(MutableTuple):
__slots__ = 'first', 'last', 'grade' # customize
>>> student = Student('Lisa', 'Simpson', 'A')
>>> student
Student('Lisa', 'Simpson', 'A')
>>> first, last, grade = student
>>> first
'Lisa'
>>> last
'Simpson'
>>> grade
'A'
>>> student[0]
'Lisa'
>>> student[2]
'A'
>>> len(student)
3
>>> 'Lisa' in student
True
>>> 'Bart' in student
False
>>> student.first = 'Bart'
>>> for i in student: print(i)
...
Bart
Simpson
A
命名元组基本上是易于创建的轻量级对象类型。命名元组实例可以使用类似对象的变量解引用或标准元组语法来引用。它们可以类似于struct或其他常见的记录类型,只是它们是不可变的。它们是在Python2.6和Python3.0中添加的,尽管有一个recipe for implementation in 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
namedtuple是用于生成元组类的工厂函数。有了这个类,我们可以创建也可以按名称调用的元组。
命名元组是元组。
它能做任何事情。
但不仅仅是一个元组。
它是一个元组的特定子类,是根据您的规范以编程方式创建的,具有命名字段和固定长度。
例如,这将创建tuple的一个子类,除了具有固定长度(在本例中为3)之外,它还可以在使用tuple的任何地方使用,而不会中断。这被称为Liskov可替代性。
New in Python 3.6,我们可以使用带有
typing.NamedTuple
的类定义来创建namedtuple:上面的与下面的相同,只是上面另外有类型注释和docstring。以下是Python2+中提供的:
这将实例化它:
我们可以检查它并使用它的属性:
更深入的解释
要理解命名元组,首先需要知道元组是什么。元组本质上是一个不可变(不能在内存中就地更改)列表。
下面是使用常规元组的方法:
可以使用iterable解包来展开元组:
命名元组是元组,允许通过名称而不仅仅是索引来访问它们的元素!
你做了一个这样的名字:
您还可以使用一个名称由空格分隔的字符串,这是对API的一种更可读的使用:
您可以执行元组可以执行的所有操作(参见上文)以及以下操作:
一位评论者问道:
用
namedtuple
创建的类型基本上是可以用简单的速记法创建的类。像上课一样对待他们。在模块级定义它们,以便pickle和其他用户可以找到它们。在全局模块级别上的工作示例:
这表明查找定义失败:
在改进代码以使元组元素的语义在代码中表达时使用它们。
如果要使用具有不变数据属性且没有功能的对象,则可以使用它们而不是对象。
您还可以subclass them to add functionality, for example:
从使用命名元组切换到元组可能是一种回归。前期设计决策的核心是,当使用元组时,所涉及的额外代码的成本是否值得提高可读性。
命名元组与元组之间没有使用额外的内存。
您要寻找的是一个时隙对象,它实现了静态大小的列表的所有功能,或者是一个工作方式类似于命名元组的子类列表(它以某种方式阻止了列表的大小变化)
一个现在已经扩大的,甚至可能是Liskov可替代的,第一个例子:
使用时,只需子类化并定义
__slots__
:命名元组基本上是易于创建的轻量级对象类型。命名元组实例可以使用类似对象的变量解引用或标准元组语法来引用。它们可以类似于
struct
或其他常见的记录类型,只是它们是不可变的。它们是在Python2.6和Python3.0中添加的,尽管有一个recipe for implementation in Python 2.4。例如,通常将点表示为元组
(x, y)
。这将导致如下代码:使用命名元组,它变得更可读:
但是,命名元组仍然与普通元组向后兼容,因此以下操作仍然有效:
因此,您应该使用命名元组而不是元组,只要您认为对象表示法将使您的代码更具python性,并且更易于阅读。我个人已经开始使用它们来表示非常简单的值类型,特别是当将它们作为参数传递给函数时。它使函数更具可读性,而不必查看元组打包的上下文。
此外,您还可以替换普通的不可变的类,这些类没有函数,只有字段。甚至可以将命名元组类型用作基类:
但是,与元组一样,命名元组中的属性是不可变的:
如果希望能够更改值,则需要其他类型。有一个方便的mutable recordtypes配方,允许您为属性设置新值。
但是,我不知道任何形式的“命名列表”允许您添加新字段。你可能只想在这种情况下用字典。命名元组可以使用返回
{'x': 1.0, 'y': 5.0}
的pt1._asdict()
转换为字典,并且可以使用所有常用的字典函数进行操作。如前所述,您应该check the documentation获取构造这些示例的更多信息。
相关问题 更多 >
编程相关推荐