简体   繁体   中英

python assigning variable mess

I'm trying to write a script that 1. lists the content of a directory, creates a list of it(temp.txt), turns the list into a string and writes it into a file 2. opens an other text file(t.txt) and compares the content of the opened file with the previously saved file (temp.txt) and returns the difference. The idea is that the script would be able to tell if there are new files in a folder. The function dif works great as a standalone script but when nested as a function I get this error message:

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

and the script:

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)

Use global li inside your functions. From what I understand, the Python interpreter will look for globals at the global scope only if it cannot find them locally. It is enough that they are set somewhere in the local method (even if it's after a possible "read") for the interpreter to bind them to local scope, thus ignoring any global declaration and resulting in the error that you see.

For instance:

a = 3

def b():
    print a
    a = 1

Will fail, even though a is defined globally at the time the print statement is executed. Adding global a at the beginning of the function body would make it work.

There are numerous conceptual problems here. For the sake of actually teaching something, I've gone over the code completely:

  • A print after an unconditional return can't be reached; I guess you had these in for debugging, but there's no point keeping them around. (I'm assuming print li from dir is not really needed either.)

  • Your function names should do a better job of indicating what the function actually does. open_file is a useless name, since the function actually does something with the file's contents.

  • Variable names, similarly, ought to indicate the meaning of the variable's contents. If you can't come up with a good name, it's a sign that the variable is unnecessary. Another sign is that you store the value once and then use it once; the only reason to involve a variable here is to break up an expression and give something a name, but here you have simple expressions and no good names. So just write out a single expression.

  • You presumably want to write the directory list as a list of lines, so join them with newlines, not commas.

  • There are even simpler ways to get a list of the lines in a file, than reading the entire file and splitting up the resulting string. They'll generally be more efficient, too. In fact, you don't need to construct the list and then build a set from the list; you can create the set directly.

  • open_file and open_another perform the same task, and thus are redundant. Just pass in a filename and use it.

  • Try to separate responsibilities of functions into logical blocks. In particular, don't handle I/O in the same place that you do the calculations.

  • In modern Python, we use with blocks to handle automatically closing the file when we're done with it.

  • os.listdir already creates a list, so there is no reason to make a loop to append the list items to another list. You could, for example, append the whole thing at once with + ; but your apparent intent is to append to an empty list, so you could just assign directly. In fact, there is no need for the global variable or the assignment, so we'll just use the os.listdir result directly.

Your program can be this simple:

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')

(And that assumes that creating the directory file is actually a requirement...)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM