Инициализировать список объектов в Python - PullRequest
13 голосов
/ 27 ноября 2009

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

Object lst = new Object[100];

Я покопался, но есть ли Pythonic способ сделать это?

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

lst = [Object()]*100

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

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

Понимание списка выглядит (интеллектуально) как «большая» работа для чего-то такого простого в Java.

Ответы [ 4 ]

31 голосов
/ 27 ноября 2009

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

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

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

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

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

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

lst = [None] * 100
12 голосов
/ 27 ноября 2009

Вы должны заметить, что Python эквивалентен коду Java (создание массива из 100 null ссылок на объект):

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 () для каждого из этих объектов

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

2 голосов
/ 27 ноября 2009

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

0 голосов
/ 27 ноября 2009
lst = [Object() for i in range(100)]

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

...