I've been searching online for a while now and can't seem to find anything. I'm basically learning a few languages and I am just trying to recreate a program in different languages.
def read_one_file():
f = open('C:\Python27\inventory.dat', 'r')
invid = f.readline()
stock = f.readline()
published = f.readline()
price = f.readline()
invtype = f.readline()
title = f.readline()
author = f.readline()
return invid, stock, published, price, invtype, title, author
read_one_file()
print "Update Number In Stock"
print "----------------------"
print "Item ID: ", invid
Basically I'm trying to read in a file, absorb the data into variables then pass those variables to the main(class?). When I return them they're still not able to be printed. When I initialize them outside of read_one_file they still don't return the right thing.
5 Answers 5
You need to store the results of read_one_file() somewhere. What you're really doing with your return statement is creating a tuple of the results. You then have to unpack that tuple when you call read_one_file. Here is an example:
(invid, stock, published, price, invtype, title, author) = read_one_file()
print "Item ID:", invid
This syntax is performing something called "pattern matching" and what it does is break up the tuple that read_one_file returns and gives names to each of element in it. I added the parenthesis here to make it clearer that read_one_file is returning a tuple, but you could just as easily write it like this:
invid, stock, published, price, invtype, title, author = read_one_file()
That's all well and good, but really, this is sort of a bad way to return things from your function. If you have a lot of variables you want to return from a function like this, a dict is probably a better way to go. Also, you'll probably want to use a with statement to ensure your file is closed and cleaned up properly once you're done with it. Here is what your code would look like using that strategy:
def read_one_file():
with open('C:\Python27\inventory.dat', 'r') as f:
return dict(invid = f.readline().strip(),
stock = f.readline().strip(),
published = f.readline().strip(),
price = f.readline().strip(),
invtype = f.readline().strip(),
title = f.readline().strip(),
author = f.readline().strip())
results = read_one_file()
print "Update Number In Stock"
print "----------------------"
print "Item ID: ", results['invid']
Edit: I changed the code above to use .strip(), since (as @NiklasB. pointed out), newlines are still included with just readline.
11 Comments
This is a bit cleaner for what you seem to be trying to do. Note I'm assuming your inventory.dat file isn't really huge, and has at least 7 lines.
def read_one_file(fname=r'C:\Python27\inventory.dat'):
with open(fname) as f:
lines = [line.strip() for line in f]
keys = ['invid', 'stock', 'published', 'price', 'invtype', 'title', 'author']
inventory_item = dict(zip(keys, lines[:len(keys)]))
return inventory_item
d = read_one_file()
print("Update Number In Stock")
print("----------------------")
print("Item ID: ", d['invid'])
Breakdown of changes from your original code:
fnamepassed as default argument, rather than hardcoded into the functionfnamestring made into ar'raw string'with therprefix, which would prevent backslash escapes from being handled wrongly (image for example if your filename wasninventory.dat, with the\as a path separator in windows you would get a newline in the filename if you were using a normal string)- file opened with context manager, to ensure it is closed properly. Read about Python's
withstatement for details. [line.strip() for line in f]is a list comprehension to remove the trailing newlines from your data and store the lines in a list calledlines.- list of keys defined, and then the first
nlines of the file are mapped as the values of the keys, using a pythondict. lines[:len(keys)]slices the list to the first n items, wherenis the number of keys declared above.zipjust pairs up 2 iterables (in this case keys and the values from file) into an iterable of tuples, which is one of the accepted forms when creating a newdict.d = read_one_file()stores the result of the file read into a variable. in your code this was being lost because there was no reference to the return value of the function held.d['invid']accesses the value of the key'invid'stored in the dictd. you should access the other values similarly.
1 Comment
This should work:
def read_one_file():
f = open('C:\Python27\inventory.dat', 'r')
invid = f.readline()
stock = f.readline()
published = f.readline()
price = f.readline()
invtype = f.readline()
title = f.readline()
author = f.readline()
return invid, stock, published, price, invtype, title, author
invid, stock, published, price, invtype, title, author = read_one_file()
print "Update Number In Stock"
print "----------------------"
print "Item ID: ", invid
Basically, you're returning what's called a "tuple" of variables from the function and assigning it to a "tuple" of variables in the main program. The fact that they are named the same thing is not really important to the program.
4 Comments
readline are included into the data strings. Furthermore, as already mentioned, it leaks an open file.Another option is to pass a dictionary in the function call, and then access the variables from the dict:
read_file_dict = {}
def read_one_file(some_dict):
...
some_dict['invid'] = file.readline()
some_dict['stock'] = file.readline()
...
Run the function:
read_one_file(read_file_dict)
And then access the variables (dict entries):
read_file_dict['invid']
Comments
The short answer: As others have stated, you need to unpack the tuple you're returning, and then the values will be available to you:
invid, stock, published, price, invtype, title, author = read_one_file()
The long answer: This might be a tad long, but bear with me, because it is important information in understanding how various programming languages work. The problem you're having is an understanding of scope, the lifetime of variables in certain scopes, and how variables can be transferred between two different scopes. I'll do my best to touch on each of these, and how it relates to your problem.
Scope is essentially a section of your program in which certain variables you declare will exist. When you defined the function:
def read_one_file():
f = open('C:\Python27\inventory.dat', 'r')
invid = f.readline()
stock = f.readline()
published = f.readline()
price = f.readline()
invtype = f.readline()
title = f.readline()
author = f.readline()
return invid, stock, published, price, invtype, title, author
you defined the scope. The variables invid, stock, published, price, invtype, title, and author all exist in that function, and cease to exist once that function terminates. Python happens to be a very good visualizer of scope, since it is space/tab dependent. A new indentation level defines a new scope.
In order to get a variable/value out of the scope of a function, you can return it, as you have done in your function. But the portion of your program which is calling the function, has to specify variables in its own scope which will receive the values the function is returning. (And to receive the data, you assign the variable to result of the function: var = function() )
In your posted code, you called read_one_file() but did not assign any variables to its returned values. When you tried to access one of the values you thought you were returning:
print "Update Number In Stock"
print "----------------------"
print "Item ID: ", invid
invid is not technically a variable outside of read_one_file(), so an error occurs.
The key is that returning variables does not automatically transfer them, by name, to the scope of the callee (the code calling the function). You must specify a new variable in the callee to receive the returned value.
Hope this helps :)