什么是“命名元组"?在 Python 中? [英] What are "named tuples" in Python?

查看:60
本文介绍了什么是“命名元组"?在 Python 中?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

阅读 Python 3.1 中的变化,我发现了一些……意想不到的东西:

<块引用>

sys.version_info 元组现在是一个命名元组:

我以前从未听说过命名元组,我认为元素可以由数字(如元组和列表)或键(如字典)索引.我从没想过它们可以双向编入索引.

因此,我的问题是:

  • 什么是命名元组?
  • 如何使用它们?
  • 为什么/何时应该使用命名元组而不是普通元组?
  • 为什么/何时应该使用普通元组而不是命名元组?
  • 是否有任何类型的命名列表"(命名元组的可变版本)?

解决方案

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

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

pt1 = (1.0, 5.0)pt2 = (2.5, 1.5)从数学导入 sqrtline_length = sqrt((pt1[0]-pt2[0])**2 + (pt1[1]-pt2[1])**2)

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

from collections import namedtuplePoint = namedtuple('Point', 'x y')pt1 = 点(1.0, 5.0)pt2 = 点(2.5, 1.5)从数学导入 sqrtline_length = sqrt((pt1.x-pt2.x)**2 + (pt1.y-pt2.y)**2)

然而,命名元组仍然向后兼容普通元组,因此以下仍然有效:

Point = namedtuple('Point', 'x y')pt1 = 点(1.0, 5.0)pt2 = 点(2.5, 1.5)从数学导入 sqrt# 使用索引引用line_length = sqrt((pt1[0]-pt2[0])**2 + (pt1[1]-pt2[1])**2)# 使用元组解包x1, y1 = pt1

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

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

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

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

<预><代码>>>>Point = namedtuple('Point', 'x y')>>>pt1 = 点(1.0, 5.0)>>>pt1.x = 2.0属性错误:无法设置属性

如果您希望能够更改这些值,则需要另一种类型.可变记录类型有一个方便的方法,它允许您为属性设置新值.><预><代码>>>>从 rcdtype 导入 *>>>Point = recordtype('Point', 'x y')>>>pt1 = 点(1.0, 5.0)>>>pt1 = 点(1.0, 5.0)>>>pt1.x = 2.0>>>打印(pt1[0])2.0

不过,我不知道有任何形式的命名列表"可以让您添加新字段.在这种情况下,您可能只想使用字典.命名元组可以使用 pt1._asdict() 转换为字典,它返回 {'x': 1.0, 'y': 5.0} 并且可以使用所有常用的字典函数.

如前所述,您应该查看文档 了解构建这些示例的更多信息.

Reading the changes in Python 3.1, I found something... unexpected:

The sys.version_info tuple is now a named tuple:

I never heard about named tuples before, and I thought elements could either be indexed by numbers (like in tuples and lists) or by keys (like in dicts). I never expected they could be indexed both ways.

Thus, my questions are:

  • What are named tuples?
  • How to use them?
  • Why/when should I use named tuples instead of normal tuples?
  • Why/when should I use normal tuples instead of named tuples?
  • Is there any kind of "named list" (a mutable version of the named tuple)?

解决方案

Named tuples are basically easy-to-create, lightweight object types. Named tuple instances can be referenced using object-like variable dereferencing or the standard tuple syntax. They can be used similarly to struct or other common record types, except that they are immutable. They were added in Python 2.6 and Python 3.0, although there is a recipe for implementation in Python 2.4.

For example, it is common to represent a point as a tuple (x, y). This leads to code like the following:

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)

Using a named tuple it becomes more readable:

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)

However, named tuples are still backwards compatible with normal tuples, so the following will still work:

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

Thus, you should use named tuples instead of tuples anywhere you think object notation will make your code more pythonic and more easily readable. I personally have started using them to represent very simple value types, particularly when passing them as parameters to functions. It makes the functions more readable, without seeing the context of the tuple packing.

Furthermore, you can also replace ordinary immutable classes that have no functions, only fields with them. You can even use your named tuple types as base classes:

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

However, as with tuples, attributes in named tuples are immutable:

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

If you want to be able change the values, you need another type. There is a handy recipe for mutable recordtypes which allow you to set new values to attributes.

>>> 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

I am not aware of any form of "named list" that lets you add new fields, however. You may just want to use a dictionary in this situation. Named tuples can be converted to dictionaries using pt1._asdict() which returns {'x': 1.0, 'y': 5.0} and can be operated upon with all the usual dictionary functions.

As already noted, you should check the documentation for more information from which these examples were constructed.

这篇关于什么是“命名元组"?在 Python 中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆