Инициализировать список объектов в Python

Я ищу инициализировать массив/список объектов, которые не являются пустыми - конструктор класса генерирует данные. В С++ и Java я бы сделал что-то вроде этого:

Object lst = new Object[100];

Я вырыл вокруг, но есть ли способ для Pythonic сделать это?

Это не работает, как я думал, это будет (я получаю 100 ссылок на один и тот же объект):

lst = [Object()]*100

Но это похоже на то, как я хочу:

lst = [Object() for i in range(100)]

Понимание списка кажется (интеллектуально) похожим на "много" работы на что-то настолько простое в Java.

Ответ 1

Невозможно косвенно вызвать конструктор Object() для каждого элемента массива, как есть в С++ (напомним, что в Java каждый элемент нового массива инициализируется для null для ссылочных типов).

Я бы сказал, что ваш метод распознавания списка является самым Pythonic:

lst = [Object() for i in range(100)]

Если вы не хотите наступать на лексическую переменную i, тогда соглашение в Python должно использовать _ для фиктивной переменной, значение которой не имеет значения:

lst = [Object() for _ in range(100)]

Для эквивалента аналогичной конструкции в Java вы можете, конечно, использовать *:

lst = [None] * 100

Ответ 2

Следует отметить, что эквивалент Python для кода Java (создание массива из 100 null ссылок на Object):

Object arr = new Object[100];

или код С++:

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.


Примечание: Код С++:

Object *arr = new Object[100];

должен был бы выполнить такую ​​же работу, как понимание списка Python:

  • выделить непрерывную память для 100 объектов

  • вызов Object:: Object() для каждого из этих объектов

И результатом будет совершенно другая структура данных.

Ответ 3

Я думаю, что понимание списка - это самый простой способ, но если вам это не нравится, это, очевидно, не единственный способ получить то, что вы хотите, - называть данный вызываемый 100 раз без аргументов, чтобы сформировать 100 элементов нового списка. Например, itertools может, очевидно, сделать это:

>>> import itertools as it
>>> lst = list(it.starmap(Object, it.repeat((), 100)))

или, если вы действительно традиционалист, map и apply:

>>> lst = map(apply, 100*[Object], 100*[()])

Обратите внимание, что это по сути то же самое (крошечный, как концептуально, так и фактически;-) объем работы, который потребуется, если вместо необходимости вызывать без аргументов Object необходимо вызвать с одним аргументом - или, скажем, если Object была фактически функцией, а не типом.

С вашего удивления, что для выполнения этой задачи может потребоваться "столько, сколько нужно для понимания списка", вы, кажется, думаете, что каждый язык должен в особом случае требовать выполнения "вызовов типа, без аргументов" по ​​другим видам звонков на вызовы, но я не понимаю, что так важно и особенно в этом конкретном случае, чтобы оправдать его по-разному от всех остальных; и, как следствие, я очень доволен, лично, что Python не выделяет этот один случай для странного и странного обращения, но обрабатывает так же регулярно и легко, как и любой другой подобный вариант использования! -)

Ответ 4

lst = [Object() for i in range(100)]

Поскольку массив - это собственный объект первого класса в python, я думаю, что это единственный способ получить то, что вы ищете. * делает что-то безумное.