字符串的Python循环 - 为什么'none'来了?

时间:2016-12-09 03:44:14

标签: python for-loop parallels

使用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

5 个答案:

答案 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)

Noneprint0(s)的返回值。使用打印时,结果将仅显示在标准输出中,但不会作为该函数的结果返回。因此,理解列表将函数评估为None。 你的功能应该是:

def print0(s):
    return s

答案 3 :(得分:0)

我经常看到这样的问题,应该有一些最终的答案,只要printNone出现在一个问题中就会自动触发...

虽然问题本身的答案是微不足道的,但我认为,你需要真正理解的是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)