2009-11-27 2 views
10

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

Object lst = new Object[100]; 

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

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

lst = [Object()]*100 

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

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

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

ответ

26

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

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

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

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

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

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

lst = [None] * 100 
+1

+1. Я бы предложил xrange вместо диапазона. – orip

+0

Справедливая точка; Недавно я был в Python 3. :) –

+1

@orip В Python 3, 'range()' делает то, что 'xrange()' используется, а 'xrange()' не существует. Если вы хотите написать код, который будет работать как на Python 2, так и на Python 3, вы не сможете использовать 'xrange()'. –

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

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

2

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

Я чувствую, что вы слишком много.Что-то простое, как это НЕ потребуется импорт других модулей – inspectorG4dget

+0

Хороший вопрос об особом случае - я думаю, я не думал об этом с этой точки зрения. Эта линия карты действительно опрятная - я еще не играл с картами, поэтому мне придется поиграть с ней. – bradreaves

+0

Ах, но @Inspector, вы видите, решение map/apply не требует никакого импорта, но это не делает его менее сложным, чем itertools: он просто использует старые вещи, которые, как оказалось, помещались во встроенные много, много лет назад, в то время как itertools является более новой идеей и надлежащим образом помещается в свой собственный модуль стандартной библиотеки. 'apply' исчез в Python 3, а' map' изменился. Итак, вы видите: ваше восприятие того, что сложно (на основе такого совершенно несоответствующего критерия, как использование импорта или нет!) Действительно полностью, принципиально неправильно и неуместно. –

11

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

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

Смежные вопросы