Reputation: 3
TL;DR How can I pass two types of data (e.g a dictionary and a list) from a function to a dictionary and a list in the global namespace?
I'm writing a script which interacts with my equipment. The script requires a user to provide multiple text files which contain CSVs. These values are then put into a list and a dictionary where appropriate.
Because the files are going to be processed in the same fashion, I've put the processing code in a function (in the spirit of DRY). The problem is that I want to append all of the list entries into a single list and all of the dictionaries entries into a single dictionary regardless of how many times the function runs, however, I'm having a trouble with the scoping side of this.
From my understanding, functions reside in the local namespace. Because of this, I'm unable to make the function append data into a 'master' list and dictionary in the global namespace (without using 'global' variables, which of course is a no no).
I know I can return the values from the function to make the data available in the global namespace, but from what I understand I can only return them in one form, e.g tuple, dictionary, etc. If this is the case, it won't suit my needs either.
My question is, how can I pass two types of data (e.g a dictionary and a list) from a function to a dictionary and a list in the global namespace?
Upvotes: 0
Views: 43
Reputation: 77357
Its not the global
keyword that's a no-no, its the 'master' list and dictionary in the global namespace itself. The problem is that you've reduced overall flexibility (what if some other code wants to import the module and manage its own containers) and made the code less obvious to manage (you need to track down all the places where these containers are touched). Those are design trade-offs and may be reasonable to accept in your environment.
Because these are containers and you can read variables from the module-global namespace in a function (you just can't reassign them), you can use them without the global
keyword. Notice that you are still using global variables.
my_list = []
my_dict = {}
def func():
while True:
filename = input("Enter csv file, or 'done'")
if filename == 'done':
break
my_list.append(filename)
# not sure what to add to dict, but you get the point
def main():
# this adds to the global containers
func()
# but be careful, this adds to the global containers and skips these
# local versions
my_list = ['foo']
my_dict = {'bar':'baz'}
func() # doesn't change the local objects
You can decouple the containers from the global namespace by passing them to the function as needed.
def func(my_list, my_dict):
while True:
filename = input("Enter csv file, or 'done'")
if filename == 'done':
break
my_list.append(filename)
# not sure what to add to dict, but you get the point
def main():
# this adds to the local containers
my_list = ['foo']
my_dict = {'bar':'baz'}
func(my_list, my_dict)
You can also start bundling these containers into your own class. This is more of a heavy lift as you might want to put more of the functions that use these containers into the class also.
class MyContainers:
def __init__(self):
self.my_list = []
self.my_dict = {}
def func(self):
while True:
filename = input("Enter csv file, or 'done'")
if filename == 'done':
break
self.my_list.append(filename)
# not sure what to add to dict, but you get the point
def main():
foo = MyContainers()
foo.func()
print(foo.my_list)
print(foo.my_dict)
Upvotes: 0
Reputation: 144
def func():
return [1,2], {'abc':5}
alist, dictionary = func()
print alist, dictionary
Output: [1,2] {'abc': 5}
print type(alist), type(dictionary)
Output: (type 'list') (type 'dict')
Upvotes: 1