2010-07-07 2 views
3

Есть ли более Pythonic способ сделать это ?:Есть ли более Pythonic способ изменения `None` в` [] `, чем

  if self.name2info[name]['prereqs'] is None: 
       self.name2info[name]['prereqs'] = [] 
      if self.name2info[name]['optionals'] is None: 
       self.name2info[name]['optionals'] = [] 

Причина Я делаю это потому, что мне нужно перебрать те позже. Они начинаются с None, потому что это значение по умолчанию. Мое обходное решение не делает [] значением по умолчанию.

Спасибо.

+8

Вы не можете изменить значение по умолчанию на [] в первую очередь (я предполагаю, что вы используете 'defaultdict')? –

+0

Нет, нет. Я использовал их раньше, но не так много. Вероятно, это было бы полезно в этом случае. Благодаря! –

ответ

4

Если вы предпочитаете это:

self.name2info[name]['prereqs'] = self.name2info[name]['prereqs'] or []

+0

Как 'None', так и' [] 'оценивать' False', не так ли? Почему это работает? –

+2

@Alex: да, [] будет оценивать значение False, поэтому, если запись уже является пустым списком, она будет заменена другим пустым списком. Единственный раз, когда это будет проблемой, - если вы хотите, чтобы несколько записей ссылались на один и тот же список - большую часть времени, когда вы этого не хотите, и наличие нескольких ссылок на один и тот же список может вызвать тонкие ошибки (например,при использовании пустого списка в качестве параметра по умолчанию для функции, которая является общей ошибкой новичка). –

+4

Если вы бросаете явный тест 'is None ', вы в основном заменяете все, что ** оценивает ** на' False' в булевом контексте с пустым списком: 'None', но также' '' '(пустая строка),' [] '(пустой список),' {} '(пустой dictiontary),' 0' (ноль), 'False' (boolean). В какой-то момент это может стать фактором для усложнения ошибок. – ChristopheD

0

Вы могли бы сделать это следующим образом:

if not self.name2info[name]['prereqs']: self.name2info[name]['prereqs'] = [] 

или таким образом

self.name2info[name]['prereqs'] = [] if not self.name2info[name]['prereqs'] else self.name2info[name]['prereqs'] 
+3

Что, если 'self.name2info [name] ['prereqs']' содержит 'False' вместо' None'? Я думаю, что вы должны явно проверить для None с 'if x is None' ... – ChristopheD

+0

Я полагаю, это зависит от того, что он хочет - это выглядит (из его кода), что' prereqs' будет либо None, либо список значения. Даже одноэлементный список '[False]' равен True. Конечно **, если OP планирует хранить любые значения, кроме списка или None, тогда вы правы **. Но если 'prereqs' всегда будет содержаться в списке, то мой метод вполне уместен. –

1

Если вы не можете исправить вход вы может сделать это (становится «лучше», если вам нужно добавить больше):

for prop in ['prereqs', 'optionals']: 
    if self.name2info[name][prop] is None: 
     self.name2info[name][prop] = [] 

Но вместо этих значений будут перебор над пустым списком вы только что добавили не делает много смысла (если возможно, если вы не добавляя что-то в этот список в какой-то момент). Так что, может быть, вы могли бы просто переместить тест на None -ness прямо перед итерацией:

prereqs = self.name2info[name]['prereqs'] 
if prereqs is not None: 
    for prereq in prereqs: 
     do_stuff(prereq) 

Слегка поднятием темы сейчас, но если вы хотите, чтобы проверить, если элемент итерация вообще, общие (вещий) можно было бы написать:

try: 
    my_iterable_obj = iter(my_obj) 
except TypeError: 
    # not iterable 
0

Каждый из этих атрибутов и запросов dict требует времени и обработки. Это вещий смотреть вверх self.name2info [имя] только один раз, а затем работать с временным именем, связанным с этой Dict:

rec = self.name2info[name] 
for key in "prereqs optionals required elective distance".split(): 
    if key not in rec or rec[key] is None: 
     rec[key] = [] 

Теперь, если нужно добавить еще одну категорию, как «AP_credit», вы просто добавить, что к строке имен ключей.

0

Если вы повторяете их, я полагаю, что они хранятся в списке. В этом случае, вероятно, было бы лучше сочетать некоторые из вышеуказанных подходов.

seq=list(map(lambda x: x or [], seq)) 

Это лаконичный способ сделать это. Насколько мне известно, преобразования в map() быстрее, чем явные для циклов, поскольку циклы выполняются в базовом C-коде.

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