2016-12-09 28 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) 
相關問題