2012-05-14 112 views
1

我想寫一個腳本,1.列出目錄的內容,創建一個列表(temp.txt),將列表變成一個字符串,並將其寫入文件2。打開另一個文本文件(t.txt),並將打開的文件的內容與先前保存的文件(temp.txt)進行比較並返回差異。這個想法是,腳本能夠判斷文件夾中是否有新文件。該功能DIF作爲一個獨立的腳本的偉大工程,但作爲嵌套函數時,我收到此錯誤信息:蟒蛇分配變量混亂

Enter directory > /users 
Traceback (most recent call last): 
    File "/Users/alkopop79/NetBeansProjects/comparefiles.py", line 33, in <module> 
    dir() 
    File "/Users/alkopop79/NetBeansProjects/comparefiles.py", line 12, in dir 
    li.append(fname) 
UnboundLocalError: local variable 'li' referenced before assignment 

和腳本:

import os 

li = [] 
lu = [] 
le = [] 

def dir(): 
    dir = raw_input("Enter directory > ") 
    path=dir # insert the path to the directory of interest 
    dirList=os.listdir(path) 
    for fname in dirList: 
      li.append(fname) 
    li = ','.join(str(n) for n in li) 
    targetfile = open("temp.txt", 'w') 
    targetfile.write(li) 
    targetfile.close() 
    print li 

def open_file(): 
    txt = open('t.txt') 
    li = txt.read() 
    la = li.split() 
    return la 
    print len(li) 

def open_another(): 
    txt = open('temp.txt') 
    lu = txt.read() 
    lo = lu.split() 
    return lo 
    print len(li) 

dir() 
a = open_file() 
b = open_another() 
print set(a) & set(b) 
+2

我的基本建議是要避免使用全局變量('li','lu','le')。請記住,Python函數可以接受參數並可以返回一個或多個值。 – NPE

+0

'dir'是一個內置函數的名稱,不應該像這樣隱藏。 –

回答

1

使用global li你的函數中。據我所知,Python解釋器只會在全局範圍內找不到全局範圍的全局變量。只要將它們設置在本地方法的某個地方就足夠了(即使是在可能的「讀取」之後)解釋器將它們綁定到本地作用域,從而忽略任何全局聲明並導致您看到的錯誤。

例如:

a = 3 

def b(): 
    print a 
    a = 1 

會失敗,即使a在執行print聲明時全局定義。在函數體的開始部分添加global a將使其工作。

+2

雖然這*可以*用於解決OP的問題,但我認爲這從長遠來看不是很好的建議。我認爲首先要避免全局變量要好得多(特別是在像這樣簡單的情況下)。 – NPE

+0

@aix:完全同意,但我試圖提供一個洞察力,爲什麼錯誤首先發生。 – ubik

+0

感謝您的想法,這非常有幫助! – alkopop79

0

這裏有很多概念問題。對於實際教學東西的緣故,我已經走了完全的代碼:

  • 一個print無條件return無法達成後;我想你已經有了這些內容進行調試,但沒有關係。 (我假設print lidir也不是真的需要。)

  • 您的函數名稱應該更好地指示函數的實際功能。 open_file是一個沒用的名字,因爲函數實際上對文件的內容做了些什麼。

  • 變量名同樣應該表示變量內容的含義。如果你不能提出一個好名字,這是一個變量是不必要的標誌。另一個跡象是,你存儲一次值,然後使用一次;在這裏涉及變量的唯一理由是分解一個表達式並給出一個名字,但是在這裏你有簡單的表達式和沒有好名字。所以只需寫出一個表達式。

  • 你可能想把目錄列表寫成行列表,所以把它們換成換行符而不是逗號。

  • 有一種更簡單的方法可以獲取文件中的行列表,而不是讀取整個文件並分割結果字符串。他們通常也會更有效率。事實上,你不需要構造列表,然後從列表中構建一個集合;你可以直接創建集合。

  • open_fileopen_another執行相同的任務,因此是多餘的。只需傳入一個文件名並使用它。

  • 嘗試將功能的責任分成邏輯塊。特別是,不要在與計算相同的地方處理I/O。

  • 在現代Python中,我們使用with塊來處理自動關閉文件,當我們完成它。

  • os.listdir已經創建了一個列表,所以沒有理由做一個循環來將列表項添加到另一個列表中。例如,你可以用+一次追加整個事物;但你明顯的意圖是追加到一個空的列表,所以你可以直接分配。實際上,不需要全局變量或賦值,所以我們直接使用os.listdir結果。

您的程序可以這麼簡單:

import os 

def make_dirfile(directory): 
    with open('temp.txt', 'w') as dirfile: 
     dirfile.write('\n'.join(os.listdir(directory))) 

def unique_lines_of(filename): 
    with open(filename) as input_file: 
     return set(input_file) 

make_dirfile(raw_input("Enter directory > ")) 
print unique_lines_of('temp.txt') & unique_lines_of('t.txt') 

(這假定創建目錄文件實際上是一個要求......)

+0

哇,謝謝!那很棒! – alkopop79

+0

什麼是'與'...'是'位?這是如何運作的? – alkopop79

+0

http://docs.python.org/whatsnew/2.5.html#pep-343-the-with-statement是我能夠快速找到的最佳總結,儘管它可能比您需要或想要的更多信息。無論如何,取決於你的意思是「如何」。 –