使用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]
我想知道为什么这里有两个'None'值,因为当我使用方法1时这两个值不会出现?我想通过使用并行技术来执行for循环,但是使用
'无'值,来自delayed
包的joblib
函数无效。谢谢。
更新:如果我想要并行:
Parallel(n_jobs=2)(delayed(print0)(seq) for seq in seqs)
它会给出错误信息:
TypeError: expected string or Unicode object, NoneType found
答案 0 :(得分:6)
由于您正在使用交互式解释器,默认情况下为返回到顶级的任何对象打印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
这是"副作用的证明。"尽量避免一次性在两个不同地方进行更改的代码(在这种情况下,交互式解释器显示结果和函数的本地操作)。
答案 1 :(得分:3)
语法[print0(s) for s in seqs]
是List Comprehension。
它会为print0(s)
中的每个元素调用seq
,并将结果放入列表中。由于print0
不返回任何内容,因此您会获得2个None
的列表。
答案 2 :(得分:0)
None
是print0(s)
的返回值。使用打印时,结果将仅显示在标准输出中,但不会作为该函数的结果返回。因此,理解列表将函数评估为None
。
你的功能应该是:
def print0(s):
return s
答案 3 :(得分: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
没有明确的返回值,只有副作用(打印)。换句话说,它在屏幕上打印一些内容,然后不返回任何内容。在Python中, nothing 被称为None
。如果你这样称呼它:
a = print0(3)
它在控制台中打印3。但现在a
的价值是什么?
>>> print a
None
现在到列表理解。它是从函数式编程(Lisp等)借来的概念,它被称为map
。 Python中还有map
函数,因此以下两行是等效的:
[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
。但是,还有lambda函数, 的情况是
times_three = lambda x: x*3
times_three(5) #returns 15
答案 4 :(得分: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)