2012-05-14 85 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是我能够快速找到的最佳总结,尽管它可能比您需要或想要的更多信息。无论如何,取决于你的意思是“如何”。 –