Python循环的字符串 - 为什么'没有'来?
我有一个奇怪的问题,当使用python循环。这可能很简单,但对我来说很陌生。说如果我有一个字符串列表:Python循环的字符串 - 为什么'没有'来?
seqs=['AA', 'AT']
然后我想打印列表中的元素。一种方法(方法1)是使用for循环:
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循环,但是使用 'None'值,delayed
函数从joblib
包不能工作。谢谢。 更新:如果我想这样做并行:
Parallel(n_jobs=2)(delayed(print0)(seq) for seq in seqs)
它会给出错误信息:
TypeError: expected string or Unicode object, NoneType found
None
是print0(s)
返回值。使用打印时,结果将仅显示在stdout中,但不会因功能而返回。所以理解列表评估功能为None
。 你funtion应改为:
def print0(s):
return s
语法[print0(s) for s in seqs]
是List Comprehension。
它将为seq
中的每个元素调用print0(s)
并将结果放入列表中。因为print0
什么也没有返回,所以你得到一个2 None
的列表。
由于您使用的交互式解释,默认情况下将打印repr()
任何对象返回到最顶层,你看None
对象,这是得到了来自您的print0
函数的调用返回的列表。这就是为什么创建仅用于其副作用的列表是不好的做法,除了所有这些对象都存储在内存中(尽管只有一个对象,并且该列表将尽快进行垃圾回收你返回其他的东西到顶层 - 直到那时,它被存储在特殊变量_
)。
你会认识到如何解释显示任何对象的repr()
返回到顶级:
>>> 'hello'
'hello'
它是有道理的,会显示以下文字列表
>>> [print()]
[None]
而且理解相同:
>>> [print(num) for num in range(3)]
0
1
2
[None, None, None]
但它是b etter使用普通的循环。单线玩家很有趣,但并不总是理想的。
>>> 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
这是一个示范“副作用”。尽量避免一次在两个不同位置进行更改的代码(在这种情况下,交互式解释器的显示结果和函数的本地操作)。
正如你所说,没有一个是单身人士,所以我不明白你对列表/内存占用情况的看法。 –
这是一个很好的答案,因为它的深入程度如何,但它无法消除海报的任何混淆。我不认为他们对垃圾收集或好榜单实践感兴趣。 – byxor
@CharlesAddis - 如果他们使用返回一些他们不感兴趣的非单例数据的函数,那么将使用O(n)内存。当你不关心结果时,这只是编写适当循环而不是理解的另一个原因。 – TigerhawkT3
我看到这样的问题如此频繁,应该有一些终极的答案他们,每当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中被称为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
。然而,也有λ-功能,这是是情况:
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)
。 ..因为你没有返回任何东西... –
这两个片段在语义上是不同的:一个只是一个带有print语句的for循环,而另一个是使用不返回任何东西的函数创建一个list-comprehension的列表) –
除了答案中提出的内容之外,如果你不想见'None's,放弃表达式的值:'_ = [print0(s)for s seqs]''。 – DyZ