Что такое & ldquo; названные кортежи & rdquo; в питоне?

Я решил написать простую функцию для копирования многомерных int-массивов с использованием System.arraycopy

public static void arrayCopy(int[][] aSource, int[][] aDestination) {
    for (int i = 0; i < aSource.length; i++) {
        System.arraycopy(aSource[i], 0, aDestination[i], 0, aSource[i].length);
    }
}

или на самом деле я улучшил ее для моего варианта использования:

/**
 * Clones the provided array
 * 
 * @param src
 * @return a new clone of the provided array
 */
public static int[][] cloneArray(int[][] src) {
    int length = src.length;
    int[][] target = new int[length][src[0].length];
    for (int i = 0; i < length; i++) {
        System.arraycopy(src[i], 0, target[i], 0, src[i].length);
    }
    return target;
}
802
задан SilentGhost 5 June 2010 в 01:36
поделиться

3 ответа

Именованные кортежи - это, по сути, легко создаваемые, легковесные типы объектов. На экземпляры именованных кортежей можно ссылаться с помощью разыменования переменных, подобных объектам, или стандартного синтаксиса кортежей. Они могут использоваться аналогично 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

Таким образом, вам следует использовать именованные кортежи вместо кортежей везде, где вы думаете, что объектная нотация сделает ваш код более питоничным и легко читаемым. Лично я начал использовать их для представления очень простых типов значений, особенно при передаче их в качестве параметров в функции. Это делает функции более читабельными, не видя контекста упаковки кортежей.

Более того, вы также можете заменить ими обычные неизменяемые классы, у которых нет функций, только поля. Вы даже можете использовать ваши именованные кортежи в качестве базовых классов:

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

Если вы хотите иметь возможность изменять значения, вам нужен другой тип. Существует удобный рецепт для mutable recordtypes, которые позволяют задавать новые значения атрибутам.

>>> 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} и может быть обработан всеми обычными функциями словаря.

Как уже отмечалось, за дополнительной информацией, на основе которой были построены эти примеры, следует обратиться к документации.

1113
ответ дан 22 November 2019 в 21:11
поделиться

именованные кортежи обеспечивают обратную совместимость с кодом, который проверяет версию следующим образом

>>> sys.version_info[0:2]
(3, 1)

и позволяют будущему коду быть более явным, используя этот синтаксис

>>> sys.version_info.major
3
>>> sys.version_info.minor
1
28
ответ дан 22 November 2019 в 21:11
поделиться

namedtuples - отличная функция, они идеальный контейнер для данных. Когда вам нужно «хранить» данные, вы должны использовать кортежи или словари, например:

user = dict(name="John", age=20)

или:

user = ("John", 20)

Подход со словарем ошеломляет, поскольку dict изменчивы и медленнее, чем кортежи. С другой стороны, кортежи неизменяемы и легковесны, но им не хватает читабельности для большого количества записей в полях данных.

namedtuples - идеальный компромисс для двух подходов, которые имеют отличную читаемость, легкость и неизменяемость (к тому же они полиморфны!).

41
ответ дан 22 November 2019 в 21:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: