2016-12-09 30 views
2

我有一个奇怪的问题,当使用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 
+4

。 ..因为你没有返回任何东西... –

+1

这两个片段在语义上是不同的:一个只是一个带有print语句的for循环,而另一个是使用不返回任何东西的函数创建一个list-comprehension的列表) –

+0

除了答案中提出的内容之外,如果你不想见'None's,放弃表达式的值:'_ = [print0(s)for s seqs]''。 – DyZ

回答

0

Noneprint0(s)返回值。使用打印时,结果将仅显示在stdout中,但不会因功能而返回。所以理解列表评估功能为None。 你funtion应改为:

def print0(s): 
    return s 
3

语法[print0(s) for s in seqs]List Comprehension

它将为seq中的每个元素调用print0(s)并将结果放入列表中。因为print0什么也没有返回,所以你得到一个2 None的列表。

6

由于您使用的交互式解释,默认情况下将打印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 

这是一个示范“副作用”。尽量避免一次在两个不同位置进行更改的代码(在这种情况下,交互式解释器的显示结果和函数的本地操作)。

+1

正如你所说,没有一个是单身人士,所以我不明白你对列表/内存占用情况的看法。 –

+1

这是一个很好的答案,因为它的深入程度如何,但它无法消除海报的任何混淆。我不认为他们对垃圾收集或好榜单实践感兴趣。 – byxor

+1

@CharlesAddis - 如果他们使用返回一些他们不感兴趣的非单例数据的函数,那么将使用O(n)内存。当你不关心结果时,这只是编写适当循环而不是理解的另一个原因。 – TigerhawkT3

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中被称为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 
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) 
相关问题