Инициализировать список объектов в Python
-
05-07-2019 - |
Вопрос
Я хочу инициализировать массив / список объектов, которые не являются пустыми - конструктор класса генерирует данные.В C ++ и Java я бы сделал что-то вроде этого:
Object lst = new Object[100];
Я покопался, но есть ли питонический способ сделать это?
Это работает не так, как я ожидал (я получаю 100 ссылок на один и тот же объект).:
lst = [Object()]*100
Но, похоже, это работает так, как я хочу:
lst = [Object() for i in range(100)]
Понимание списка кажется (интеллектуально) "большой" работой для чего-то такого простого в Java.
Решение
Нет способа неявно вызвать конструктор Object ()
для каждого элемента массива, как в C ++ (напомним, что в Java каждый элемент нового массива инициализируется как null
для ссылочных типов).
Я бы сказал, что ваш метод понимания списка - самый питонский:
lst = [Object() for i in range(100)]
Если вы не хотите наступать на лексическую переменную i
, тогда в Python принято использовать _
для фиктивной переменной, значение которой не имеет значения
lst = [Object() for _ in range(100)]
Для эквивалента аналогичной конструкции в Java вы, конечно, можете использовать *
:
lst = [None] * 100
Другие советы
Следует отметить, что Python эквивалентен Java-коду (создание массива из 100 ноль ссылки на объект):
Object arr = new Object[100];
или код на C ++:
Object **arr = new Object*[100];
является:
arr = [None]*100
нет:
arr = [Object() for _ in range(100)]
Второй был бы таким же, как у Java:
Object arr = new Object[100];
for (int i = 0; i < arr.lenght; i++) {
arr[i] = new Object();
}
На самом деле возможности Python по инициализации сложных структур данных намного лучше, чем у Java.
Примечание:Код на C ++:
Object *arr = new Object[100];
пришлось бы проделать столько же работы, сколько и для понимания списка Python:
выделите непрерывную память для 100 объектов
вызовите Object::Object() для каждого из этих объектов
И в результате получилась бы совершенно другая структура данных.
Я думаю, что понимание списка является самым простым способом, но, если вам это не нравится, это, очевидно, не единственный способ получить то, что вы хотите - вызывать данный вызываемый объект 100 раз без аргументов для формирования 100 элементов. нового списка. Например, itertools
может сделать это:
>>> import itertools as it
>>> lst = list(it.starmap(Object, it.repeat((), 100)))
или, если вы действительно традиционалист, примените map
и
:
>>> lst = map(apply, 100*[Object], 100*[()])
Обратите внимание, что это по сути один и тот же (крошечный, как концептуально, так и фактически ;-) объем работы, который потребовался бы, если бы вместо того, чтобы вызывать без аргументов, Object
нужно вызывать с помощью один аргумент - или, скажем, если Object
на самом деле была функцией, а не типом.
К вашему удивлению, это может занять "столько же, сколько и понимание списка". чтобы выполнить эту задачу, вы, кажется, думаете, что каждый язык должен в особом случае выполнять «вызовы типа без аргументов»; из-за других видов призывов к вызовам, но я не понимаю, что же такого важного и особенного в этом очень конкретном случае, чтобы оправдать его трактовку иначе, чем в других; и, как следствие, лично я очень рад, что Python не выделяет этот единственный случай для необычного и странного обращения, но обрабатывает так же регулярно и легко, как и любой другой подобный вариант использования! -)
lst = [Object() for i in range(100)]
Поскольку массив - это собственный объект первого класса в Python, я думаю, что это единственный способ получить то, что вы ищете. * делает что-то сумасшедшее.