Я решил написать простую функцию для копирования многомерных 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;
}
Именованные кортежи - это, по сути, легко создаваемые, легковесные типы объектов. На экземпляры именованных кортежей можно ссылаться с помощью разыменования переменных, подобных объектам, или стандартного синтаксиса кортежей. Они могут использоваться аналогично 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}
и может быть обработан всеми обычными функциями словаря.
Как уже отмечалось, за дополнительной информацией, на основе которой были построены эти примеры, следует обратиться к документации.
именованные кортежи обеспечивают обратную совместимость с кодом, который проверяет версию следующим образом
>>> sys.version_info[0:2]
(3, 1)
и позволяют будущему коду быть более явным, используя этот синтаксис
>>> sys.version_info.major
3
>>> sys.version_info.minor
1
namedtuples - отличная функция, они идеальный контейнер для данных. Когда вам нужно «хранить» данные, вы должны использовать кортежи или словари, например:
user = dict(name="John", age=20)
или:
user = ("John", 20)
Подход со словарем ошеломляет, поскольку dict изменчивы и медленнее, чем кортежи. С другой стороны, кортежи неизменяемы и легковесны, но им не хватает читабельности для большого количества записей в полях данных.
namedtuples - идеальный компромисс для двух подходов, которые имеют отличную читаемость, легкость и неизменяемость (к тому же они полиморфны!).