2016-12-09 2 views
2

У меня странный вопрос при использовании цикла python. Это может быть легко, но странно для меня. Скажем, если у меня есть список строк:Python loop of strings - почему «нет»?

seqs=['AA', 'AT'] 

Затем я хочу распечатать элементы в списке. Один из способов (метод 1) заключается в использовании для цикла:

for seq in seqs: 
    print seq 

Что работает нормально. В то же время, я определяю функцию «Печать» (метод 2) для печати:

def print0(s): 
    print s 

[print0(s) for s in seqs] 

Если я использую «print0» функцию для распечатки значений, это выход:

AA 
AT 
[None, None] 

Я хочу знать, почему здесь появляются два значения «Нет», поскольку эти два значения не появляются, когда я использую метод 1? Я хочу сделать цикл for, используя технологию параллельного соединения, но с «Нет», delayed функция от joblib пакет не может работать. Благодарю. Update: если я хочу сделать это параллелью:

Parallel(n_jobs=2)(delayed(print0)(seq) for seq in seqs) 

Он выдает сообщение об ошибке:

TypeError: expected string or Unicode object, NoneType found 
+4

. .. Потому что вы ничего не возвращаете ... –

+1

оба фрагмента семантически разные: один из них только для цикла с инструкцией печати, а другой - для создания списка со списком, используя функцию, которая ничего не возвращает (ни один) –

+0

В дополнение к тому, что было предложено в ответах, если вы не хотите см. «Нет», отбросьте значение выражения: '_ = [print0 (s) для s в seqs]'. – DyZ

ответ

0

None является возвращаемым значением print0(s). При использовании печати результат будет отображаться только в stdout, но не возвращаться в результате функции. Таким образом, список осмысления оценивает функцию как None. Ваш Funtion должен быть вместо этого:

def print0(s): 
    return s 
3

Синтаксис [print0(s) for s in seqs] является List Comprehension.

Он будет называть print0(s) для каждого элемента в seq и помещать результат в список. Поскольку print0 ничего не возвращает, вы получаете список из 2 None s.

6

Поскольку вы используете интерактивный интерпретатор, который по умолчанию печатает repr() для любого объекта, возвращаемого на верхний уровень, вы увидите список None объектов, является то, что получил вернулся из вызовов вашей print0 функции. Вот почему не рекомендуется создавать список только для его побочных эффектов, в дополнение к тому факту, что все эти объекты хранятся в памяти (хотя есть только один объект None, и этот список будет собираться с мусором, как только вы возвращаете что-то еще на верхний уровень - до этого он сохраняется в специальной переменной _).

Вы узнаете, как интерпретатор отображает repr() любого объекта возвращается на верхний уровень:

>>> 'hello' 
'hello' 

И это имеет смысл, что отображается следующий буквальный список:

>>> [print()] 

[None] 

И то же для понимания:

>>> [print(num) for num in range(3)] 
0 
1 
2 
[None, None, None] 

Но это b чтобы использовать обычный цикл. Однострочники - это весело, но не всегда идеально.

>>> for num in range(3): 
...  print(num) 
... 
0 
1 
2 

Обратите внимание, что вы можете получить странные результаты, если функция печатает одно и возвращает другое:

>>> def f(): 
...  print(1) 
...  return 2 
... 
>>> [f() for num in range(3)] 
1 
1 
1 
[2, 2, 2] 
>>> for num in range(3): 
...  f() 
... 
1 
2 
1 
2 
1 
2 

Это демонстрация «побочных эффектов». Старайтесь избегать кода, который делает изменения в двух разных местах одновременно (в этом случае отображаются результаты интерактивного интерпретатора и локальные действия функции).

+1

Нет, как вы сказали, ни одного сингла, поэтому я не понимаю вашу точку зрения о занимаемой должности. –

+1

Это хороший ответ из-за того, насколько он утончен, но он не может устранить путаницу, которую имеет плакат. Я не думаю, что они заинтересованы в сборе мусора или хороших перечнях. – byxor

+1

@CharlesAddis - Если они используют функцию, которая возвращает некоторые не-одиночные данные, которые им не интересны, это будет использовать память O (n). Это просто еще одна причина для написания правильного цикла вместо понимания, когда вы не заботитесь о результате. – TigerhawkT3

0

я вижу такие вопросы так часто, должен быть какой-то окончательный ответ на них все, что автоматически вызывает каждый раз, когда print и None оба присутствуют в одном вопросе ...

Хотя ответ на этот вопрос сама по себе тривиальна, что, я думаю, вам действительно нужно понять разницу между side effect и возвращаемым значением . Например:

a = 10 
def three(x): 
    global a 
    a += x #side effect 
    print x #side effect 
    return 3 #returning 

Значение наши three() функция возвращает это 3. Она также имеет две побочные эффекты: изменение глобальной переменной a и печати. Они называются побочными эффектами, потому что они изменяют что-то вне функции: переменную a и состояние экрана соответственно.

В вашем примере:

def print0(s): 
    print s 

нет явного возвращаемого значения, только побочный эффект (печать). Другими словами, он печатает что-то на экране, а затем ничего не возвращает. Это ничего называется None в Python. Если вы так назвали:

a = print0(3) 

он печатает 3 в консоли. Но какова ценность a?

>>> print a 
None 

Теперь, чтобы узнать о понятии. Это концепция, заимствованная из функционального программирования (Lisp и т. Д.), Где она называется map. Там еще map функция в Python, поэтому следующие две строки эквивалентны:

[print0(s) for s in seqs] 
map(print0, seqs) 

То, что они оба делают принимает элементы списка ввода (seqs), один за другим, применяя функцию (print0) для каждого из них и помещать результаты (возвращаемые значения) один за другим в выходной список, который они возвращают. Каждый раз, когда они вызывают функцию print0, она выводит на экран свой аргумент s (побочный эффект), а затем ничего не возвращает (None), который помещается в выходной список по усмотрению списка или map. Если вы сделаете это в интерактивной консоли Python, этот результат появится на выходе ([None, None]), если нет - он все еще создается интерпретатором и сразу же отбрасывается, если вы не передадите его в качестве аргумента другому оператору. Это приводит нас к вашей последней строке кода и сообщению TypeError. Вы передаете свою функцию другой функции, которая ожидает строку, она не заботится о побочных эффектах, которые может вызвать ваша функция.Контекст не совсем ясно для меня, но вы, вероятно, должны определить свою функцию, как это:

def print0(s): 
    return str(s) 

Теперь, вместо того, чтобы печатать s на экране, он преобразует его в string, а затем возвращается его. Обратите внимание, что если вы вызовете их внутри интерактивного интерпретатора так же, как print0(s), похоже, они создают тот же эффект, что может быть запутанным. Однако, если вы делаете a = print0(s), вы увидите, что a отличается. В некоторых языках последнее вычисленное значение автоматически становится возвращаемым значением, но с Python, что это не так для обычных функций:

def times_three(x): 
    x*3 

возвращается None. Однако, есть также лямбда-функция, для которых что является случаем:

times_three = lambda x: x*3 
times_three(5) #returns 15 
0

Другим способом, если вы хотите сделать это в интерактивном режиме в одной гильзе использовать .join

text = ['28', '43', '6f', '72', '65', '20', '64', '6f', '6d', '70', '65', '64', '29', '0a'] 

''.join(chr(int(x, 16)) for x in text)