Assume I have a file of the following format:
a,1
b,2
c,3
d,4
Here is my code:

def junk(f):
    d1 = {}
    d2 = {}
    for line in f:
        columns = line.split(":")
        letters = columns[1]
        numbers = columns[2]
        d1[letters] = numbers
        d2[numbers] = letters
    return (d1, d2)
    
                     
def something():  
    print d1
    print d2
    
if __name__ == "__main__":
    f = open("filename.txt")
    d1 = junk(f)[0]
    d2 = junk(f)[1]

Assume I want to call function something. It cannot print d1 and d2 unless I add them to the main block. As soon as I add d1 and d2 to the "main" block and call either of the two functions, both return two empty dictionaries. Why does this happen? How can I fix it? Please help!

Recommended Answers

All 7 Replies

First you are not returning a dictionary. I've added a print statement to show that. Also, take a look at "returns" and "arguments" here http://www.penzilla.net/tutorials/python/functions/ for the "something" function.

def junk(f):
    d1 = {}
    d2 = {}
    for line in f:
        columns = line.split(":")
        letters = columns[1]
        numbers = columns[2]
        d1[letters] = numbers
        d2[numbers] = letters
    return (d1, d2)
 
 
def something():  
    print d1
    print d2
 
if __name__ == "__main__":
    f = open("filename.txt")
    d1 = junk(f)[0]
    print "type d1 =", type(d1)
    d2 = junk(f)[1]

First you are not returning a dictionary. I've added a print statement to show that. Also, take a look at "returns" and "arguments" here http://www.penzilla.net/tutorials/python/functions/ for the "something" function.

def junk(f):
    d1 = {}
    d2 = {}
    for line in f:
        columns = line.split(":")
        letters = columns[1]
        numbers = columns[2]
        d1[letters] = numbers
        d2[numbers] = letters
    return (d1, d2)
 
 
def something():  
    print d1
    print d2
 
if __name__ == "__main__":
    f = open("filename.txt")
    d1 = junk(f)[0]
    print "type d1 =", type(d1)
    d2 = junk(f)[1]

I still don't get it. The type of d1 is dictionary.

Try this and then go to the page from the earlier link which explains why you returned a tuple.

def junk(f):
    d1 = {}
    d2 = {}
    for line in f:
        columns = line.split(":")
        letters = columns[1]
        numbers = columns[2]
        d1[letters] = numbers
        d2[numbers] = letters
    return d1, d2

if __name__ == "__main__":
    f = open("filename.txt")
    d1_ret, d2_ret = junk(f)[0]
    print type(d1_ret)

Try this and then go to the page from the earlier link which explains why you returned a tuple.

def junk(f):
    d1 = {}
    d2 = {}
    for line in f:
        columns = line.split(":")
        letters = columns[1]
        numbers = columns[2]
        d1[letters] = numbers
        d2[numbers] = letters
    return d1, d2

if __name__ == "__main__":
    f = open("filename.txt")
    d1_ret, d2_ret = junk(f)[0]
    print type(d1_ret)

OK, I see that putting a comma between two variables automatically returns a tuple. But the problem is that as long as d1(d1_ret) or d2(d2_ret) in the "main" block junk(f) would return twoempty dictionaries in a tuple. That is what I don't understand.

Assume I have a file of the following format:
a,1
b,2
c,3
d,4
Here is my code:

def junk(f):
    d1 = {}
    d2 = {}
    for line in f:
        columns = line.split(":")
        letters = columns[1]
        numbers = columns[2]
        d1[letters] = numbers
        d2[numbers] = letters
    return (d1, d2)
    
                     
def something():  
    print d1
    print d2
    
if __name__ == "__main__":
    f = open("filename.txt")
    d1 = junk(f)[0]
    d2 = junk(f)[1]

Assume I want to call function something. It cannot print d1 and d2 unless I add them to the main block. As soon as I add d1 and d2 to the "main" block and call either of the two functions, both return two empty dictionaries. Why does this happen? How can I fix it? Please help!

Really just a series of somewhat careless beginner mistakes you can fix this way ...

"""assume file "filename.txt" has this content
a,1
b,2
c,3
d,4
"""

def junk(f):
    d1 = {}
    d2 = {}
    for line in f:
        columns = line.split(",")  # <---- delimiter is comma
        letters = columns[0]       # <---- index starts with 0
        numbers = columns[1]   # <---- index again
        d1[letters] = numbers
        d2[numbers] = letters
    return d1, d2

def something(d1, d2):    # <---- give function proper arguments
    print d1
    print d2

if __name__ == "__main__":
    f = open("filename.txt")
    d1, d2 = junk(f)       # expand the tuple that is returned
    something(d1, d2)  # give function its needed arguments

"""my output -->
{'a': '1\n', 'c': '3\n', 'b': '2\n', 'd': '4'}
{'3\n': 'c', '1\n': 'a', '4': 'd', '2\n': 'b'}
"""

Really just a series of somewhat careless beginner mistakes you can fix this way ...

"""assume file "filename.txt" has this content
a,1
b,2
c,3
d,4
"""

def junk(f):
    d1 = {}
    d2 = {}
    for line in f:
        columns = line.split(",")  # <---- delimiter is comma
        letters = columns[0]       # <---- index starts with 0
        numbers = columns[1]   # <---- index again
        d1[letters] = numbers
        d2[numbers] = letters
    return d1, d2

def something(d1, d2):    # <---- give function proper arguments
    print d1
    print d2

if __name__ == "__main__":
    f = open("filename.txt")
    d1, d2 = junk(f)       # expand the tuple that is returned
    something(d1, d2)  # give function its needed arguments

"""my output -->
{'a': '1\n', 'c': '3\n', 'b': '2\n', 'd': '4'}
{'3\n': 'c', '1\n': 'a', '4': 'd', '2\n': 'b'}
"""

But how come if you call the function junk again after the program finished executing and showed the output, it will return two empty dicts?

But how come if you call the function junk again after the program finished executing and showed the output, it will return two empty dicts?

Because the code is also poorly designed, ideally you should send the file name to the function, open the file there, read and close it.

You can fix your code this way ...

def junk(fh):
    d1 = {}
    d2 = {}
    for line in fh:
        columns = line.split(",")
        letters = columns[0]
        numbers = columns[1]
        d1[letters] = numbers
        d2[numbers] = letters
    return d1, d2

def something(d1, d2):
    print d1
    print d2

if __name__ == "__main__":
    fh = open("filename.txt")
    d1, d2 = junk(fh)
    something(d1, d2)
    print( '-'*50 )
    # second time around
    # file handle fh is at the end of the file now
    # reset it to the start of the file
    fh.seek(0)
    d1, d2 = junk(fh)
    something(d1, d2)

"""my output -->
{'a': '1\n', 'c': '3\n', 'b': '2\n', 'd': '4'}
{'3\n': 'c', '1\n': 'a', '4': 'd', '2\n': 'b'}
--------------------------------------------------
{'a': '1\n', 'c': '3\n', 'b': '2\n', 'd': '4'}
{'3\n': 'c', '1\n': 'a', '4': 'd', '2\n': 'b'}
"""

This would have been the better design ...

"""assume file "filename.txt" has this content
a,1
b,2
c,3
d,4
"""

def file2dictionary(fname):
    """
    read data from file and create a dictionary d1 and its reverse d2
    """
    fh = open("filename.txt")
    d1 = {}
    d2 = {}
    for line in fh:
        columns = line.split(",")
        letters = columns[0]
        numbers = columns[1]
        d1[letters] = numbers
        d2[numbers] = letters
    fh.close()
    return d1, d2

def print_dict(d1, d2):
    """print the two dictionaries d1 and d2"""
    print(d1)
    print(d2)

if __name__ == "__main__":
    fname = "filename.txt"
    d1, d2 = file2dictionary(fname)
    print_dict(d1, d2)
    print( '-'*50 )
    # test second time around
    d1, d2 = file2dictionary(fname)
    print_dict(d1, d2)

"""my output -->
{'a': '1\n', 'c': '3\n', 'b': '2\n', 'd': '4'}
{'3\n': 'c', '1\n': 'a', '4': 'd', '2\n': 'b'}
--------------------------------------------------
{'a': '1\n', 'c': '3\n', 'b': '2\n', 'd': '4'}
{'3\n': 'c', '1\n': 'a', '4': 'd', '2\n': 'b'}
"""

Note:
If you use the print() function instead of the print statement this code will work with Python2 and Python3.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.