Python цикл строк - почему "нет" приходит?
У меня странный вопрос при использовании цикла Python. Это может быть легко, но странно для меня. Скажи, если у меня есть список строк:
seqs=['AA', 'AT']
Затем я хочу распечатать элементы в списке. Одним из способов (метод 1) является использование для цикла:
for seq in seqs:
print seq
Который работает отлично. Тем временем я определяю функцию "print" (метод 2) для печати:
def print0(s):
print s
[print0(s) for s in seqs]
Если я использую функцию "print0" для вывода значений, это вывод:
AA
AT
[None, None]
Я хочу знать, почему здесь появляются два значения "Нет", поскольку эти два значения не приходят, когда я использую метод 1? Я хочу сделать цикл с использованием метода параллелизма, но со значением None, delayed
функция от joblib
пакет не может работать. Благодарю. Обновление: если я хочу сделать это параллельно:
Parallel(n_jobs=2)(delayed(print0)(seq) for seq in seqs)
Это выдаст сообщение об ошибке:
TypeError: expected string or Unicode object, NoneType found
5 ответов
Поскольку вы используете интерактивный переводчик, который по умолчанию печатает repr()
для любого объекта, возвращенного на верхний уровень, вы видите список None
объекты, то есть то, что получили от звонков вашего print0
функция. Вот почему не рекомендуется создавать список только для его побочных эффектов, в дополнение к тому факту, что все эти объекты хранятся в памяти (хотя есть только один None
объект, и этот список будет собирать мусор, как только вы вернете что-то еще на верхний уровень - до тех пор, он хранится в специальной переменной _
).
Вы узнаете, как переводчик отображает repr()
любого объекта, возвращаемого на верхний уровень:
>>> 'hello'
'hello'
И имеет смысл, что следующий буквальный список отображается:
>>> [print()]
[None]
И то же самое для понимания:
>>> [print(num) for num in range(3)]
0
1
2
[None, None, None]
Но лучше использовать обычный цикл. Однострочники это весело, но не всегда идеально.
>>> 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
Это демонстрация "побочных эффектов". Старайтесь избегать кода, который вносит изменения в двух разных местах одновременно (в этом случае отображаемые результаты интерактивного интерпретатора и локальные действия функции).
Синтаксис [print0(s) for s in seqs]
такое понимание списка
Будет звонить print0(s)
для каждого элемента в seq
и положить результат в список. Так как print0
ничего не возвращает, вы получаете список из 2 None
s.
Я вижу такие вопросы так часто, что должен быть какой-то окончательный ответ на них все, который автоматически срабатывает всякий раз, когда print
а также None
оба присутствуют в одном вопросе...
В то время как ответ на сам вопрос тривиален, я думаю, что вам действительно нужно понять, это разница между побочным эффектом и возвращаемым значением. Например:
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
Другой способ, если вы хотите сделать это в интерактивном режиме в одну строку, это использовать .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)
None
это возвращаемое значение print0(s)
, При использовании print результат будет просто отображен в stdout, но не будет возвращен как результат функции. Таким образом, список понимания оценивает функцию как None
, Ваша функция должна быть:
def print0(s):
return s