2013-01-21 55 views
9

只是一個基本的問題關於Python和。加入()方法:Python的發電機的對象和。加入

file1 = open(f1,"r") 
file2 = open(f2,"r") 
file3 = open("results","w") 

diff = difflib.Differ() 
result = diff.compare(file1.read(),file2.read()) 
file3.write("".join(result)), 

上面的代碼段產生存儲在一個所謂的「結果」的文件一個不錯的輸出,以字符串格式,逐行顯示兩個文件之間的差異。但是我注意到,如果我使用.join()打印「結果」而不是,編譯器會返回包含內存地址的消息。在嘗試使用.join()將結果寫入文件而不使用之後,編譯器通知我,只有字符串和字符緩衝區可以用於.join()方法,而不是生成器對象。所以基於關閉的所有證據,我引證,請糾正我,如果我錯了:

  1. result = diff.compare(file1.read(),file2.read()) < ----結果是一個生成器對象?

  2. result是一個字符串列表,其中result本身就是第一個字符串的引用?

  3. .join()需要一個內存地址並指向第一個,然後迭代該結構中字符串的其餘地址?

  4. 生成器對象是一個返回指針的對象嗎?

我很抱歉,如果我的問題不清楚,但我基本上想問問Python退伍軍人,如果我的推論是正確的。我的問題不在於可觀察的結果,而在於python的內部運作。我感謝你的幫助。

+0

什麼信息? – Marcin

+1

您沒有內存地址; python給你一個對象的表示,而自定義對象的默認是顯示對象的類型和內存地址。那裏還有一個對象。 –

回答

22

join是一種字符串的方法。該方法採用任何可迭代的方法並遍歷它並將內容連接在一起。 (內容必須是字符串,否則會引發異常。)

如果您嘗試將生成器對象直接寫入文件,您只需獲取生成器對象本身,而不是其內容。 join「展開」生成器的內容。

你可以看到什麼是一個簡單的,明確的發電機會:

def gen(): 
    yield 'A' 
    yield 'B' 
    yield 'C' 

>>> g = gen() 
>>> print g 
<generator object gen at 0x0000000004BB9090> 
>>> print ''.join(g) 
ABC 

發電機多爾斯出其內容一次一個。如果您嘗試查看發生器本身,它不會發現任何東西,而只是將其視爲「發生器對象」。要了解其內容,您需要對它們進行迭代。您可以使用for循環,next函數或任何其他函數/方法(其中包括str.join)執行此操作。

當你說結果「是一個字符串列表」時,你已經接近這個想法。生成器(或可迭代的)有點像「潛在列表」。而不是實際上它的所有內容一次列表,它可以讓你剝離每個項目一次。

沒有一個對象是「內存地址」。生成器對象的字符串表示(與許多其他對象類似)包含一個內存地址,所以如果您打印它(如上所述)或將其寫入文件,您將看到該地址。但是,這並不意味着該對象「是」該內存地址,並且該地址本身並不是真正可用的。這只是一個方便的識別標籤,所以如果你有多個物體,你可以區分它們。

+2

請注意,'join'假定iterable包含/只產生字符串。如果不是這樣的話,它會發生抱怨... – mgilson

+6

有趣的事實:給'''.join()'生成器*比給定'''.join()'調用'list()在發電機上。 '''.join(list(result))'比'''.join(result)'快。 –

+0

@Marcin:消息是:<發生器對象實例在0xb76526e4> – eazar001