python return two dictionaries - python

I am trying to return two dictionaries. person_to_friends and person_to_networks are given functions, and profiles_file is a text file.
What I wrote is:
def load_profiles(profiles_file, person_to_friends, person_to_networks):
"""
(file, dict of {str : list of strs}, dict of {str : list of strs}) -> NoneType
Update person to friends and person to networks dictionaries to include
the data in open file.
"""
profiles_file = open('data.txt', 'r')
person_to_friends = person_to_friends(profiles_file)
person_to_networks = person_to_networks(profiles_file)
return person_to_friends, person_to_networks
This only gives me person_to_friends dictionary..Could anyone can help this problem?
What I want to return is
{person_to_friends}
{person_to_networks}

Simply do:
return (person_to_friends, person_to_networks)
and when you call the function you need to unpack the return value:
person_to_friends, person_to_networks = load_profiles(var1, var2, var3)

You can return only one value (this value can be a tuple, as in your case). However, you can yield as much values as you need:
def load_profiles(profiles_file, person_to_friends, person_to_networks):
"""
(file, dict of {str : list of strs}, dict of {str : list of strs}) -> NoneType
Update person to friends and person to networks dictionaries to include
the data in open file.
"""
profiles_file = open('data.txt', 'r')
person_to_friends = person_to_friends(profiles_file)
person_to_networks = person_to_networks(profiles_file)
yield person_to_friends # you can do it without temp variable, obv.
yield person_to_networks
The difference is that with yield statement you don't construct a temporary tuple just to return two results at once. However, getting the values out of your "function" (that became a generator) will be slightly more difficult:
profiles = load_profiles(your args)
will not actually run your function at all, it just initializes a generator. To actually get values, you'll need to:
person_to_friends = next(profiles)
person_to_networks = next(profiles)
or just do a loop:
for result in load_profiles(your args):
do_something_with_your_dictionaries
So your function will return one value: the initialized generator object. Iterating over it in a loop (it can be for loop, map, filter, list(your_generator) or something else) or just calling next(your_generator) will give you both dictionaries you actually need.

The way you are returning two dictionaries is fine, something funny must be going on in the other parts of the code, if your remove them, everything works fine:
def load_profiles():
person_to_friends = {'a' : 1}
person_to_networks = {'b' : 2}
return person_to_friends, person_to_networks
Result:
>>> load_profiles()
({'a': 1}, {'b': 2})
>>> dict_1, dict_2 = load_profiles()
>>> dict_1
{'a': 1}
>>> dict_2
{'b': 2}

Your docstring states that the function parameter person_to_friends is a
dict of {str : list of strs}
But then you call it as though it were a function and overwrite it with the result:
person_to_friends = person_to_friends(profiles_file)
Is this a mistake in the docstring, or the code?
Possibly you are masking the real function definition by having a locally defined variable of the same name (ie the parameter). In general it is bad practice to override a variable of one type (eg function) with another vastly different type (eg dict) - although there are exceptions to this.

maybe you can try
class temp(a, b):
return dict(a=a, b=b)

Related

How to pass the structure of a dictionary into a function

I am trying to pass a dictionary that was created automatically into a function that defines the scheme of a JSON.
This is my function:
def split_line_items(df_transactions):
for row in df_transactions.itertuples():
yield {
"count_0": row.count_0,
"count_1": row.count_1,
"count_2": row.count_2,
"total_count": row.total_count
}
and this is my dictionary:
d = {'"count_0"': 'row.count_0',
'"count_1"': 'row.count_1',
'"count_2"': 'row.count_2',
'"total_count"': 'row.total_count'}
How can I pass the dictionary into the function without having to modify it manually?
EDIT: I don't want to use the data contained in the dictionary, I want to use the structure (key/values) from the dictionary to define a JSON. The example in yield {} is how it should look like.
I guess you mean something like this, however the question is not very clear.
# considering this is your tf_transactions
transactions = namedtuple('r',['count_0', 'count_1', 'count_2', 'total_count'])
tf_transactions = [transactions(1,2,3,4), transactions(1,2,3,4)]
for row in tf_transactions:
yield {k.strip('\"'): getattr(row, v.split('.')[1]) for k,v in d.items()}

Pythonic way to populate a dictionary from list of records

Background
I have a module called db.py that is basically consist of wrapper functions that make calls to the db. I have a table called nba and that has columns like player_name age player_id etc.
I have a simple function called db_cache() where i make a call to the db table and request to get all the player ids. The output of the response looks something like this
[Record(player_id='31200952409069'), Record(player_id='31201050710077'), Record(player_id='31201050500545'), Record(player_id='31001811412442'), Record(player_id='31201050607711')]
Then I simply iterate through the list and dump each item inside a dictionary.
I am wondering if there is a more pythonic way to populate the dictionary?
My code
def db_cache():
my_dict: Dict[str, None] = {}
response = db.run_query(sql="SELECT player_id FROM nba")
for item in response:
my_dict[item.player_id] = None
return my_dict
my_dict = db_cache()
This is built-in to the dict type:
>>> help(dict.fromkeys)
Help on built-in function fromkeys:
fromkeys(iterable, value=None, /) method of builtins.type instance
Create a new dictionary with keys from iterable and values set to value.
The value we want is the default of None, so all we need is:
my_dict = dict.from_keys(db.run_query(sql="SELECT player_id FROM nba"))
Note that the value will be reused, and not copied, which can cause problems if you want to use a mutable value. In these cases, you should instead simply use the dict comprehension, as given in #AvihayTsayeg's answer.
my_arr = [1,2,3,4]
my_dict = {"item":item for item in my_arr}

Receiving multiple function outputs in one line

Suppose I have multiple functions:
type = {'a', 'b', ..., 'z'}
f={}
f['a'] = some func_a...
f['b'] = some func_b...
...
f['z'] = some func_z...
Now I want to get the outputs of them
output = {}
for t in type:
output[t] = f[t](input)
I wonder if there is any way that we can do this in one line using a loop in a different way, like
[output[t] for t in type] = [f[t](input) for t in type]
Of course, this does not work. So would there be any valid way?
You want a dictionary comprehension. It works just like a list comprehension, but instead of a single expression to form the values, you get to provide two expressions to generate both a key and a value:
output = {t: f[t](input) for t in type}
The dict comprehension produces a new dictionary object; there is no need or use for an initial output = {} line.
I'd just iterate over the items of f, as it already has the keys we need:
output = {t: func(input) for t, func in f.items()}
As a side note, instead of using separate assignments for all your f functions, just use a single dictionary definition:
f = {
'a': some_func_a,
'b': some_func_b,
# ...
'z': some_func_z,
}
type is not a great name for a variable, either, as that masks the built-in function you may sometimes want to use. You don't need to create that set separately, as iteration over f would give you the same keys, or you can use set(f) to create a set copy, or f.keys(), to get a dictionary view object over the keys of f, which acts just like a set but is 'live' in that changes to f are reflected in it.

extract items from several ordered dictionaries stored in one dict object

I have a parent dictionary here that is a collection of two dictionaries X and Y. Stored them by using the DictReader of the csv module.
Lets call this dictionary example_dicto that contains two ordered dictionaries. For clarification, from the variable explorer in Spyder this looks like:
Name Type Size Value
example_dict dict 2 {'X':OrderedDict, 'Y': OrderedDict}
Ok, so I know X and Y are the main keys here. But I would like to look up values through these two dictionaries. Suppose there is a Duration column for X and Duration (min) for Y and I would like my function to read over these columns depending on a row and return their values.
def info_from_row(row, dictionary):
if dict == 'X':
duration = float(row['Duration'])
else:
duration = float(row['Duration (min)'])
return duration
When I call info_from_row, python returns the usual KeyError where the traceback is telling me that none of these 'keys' exist.
So basically I have to index a dictionary that is a collection of dictionaries and then index keys within their 'main' keys X and Y to return a value. How do I index them since the usual dict['key'] method is giving me an error and besides 'Duration' in X returns False.
For more clarification, these dictionaries look like the following:
print(example_dict)
{'X': OrderedDict([('ID', '123456'), ('Duration', '54941')]),
'Y': OrderedDict([('ID', '789101'), ('Duration (min)', '7869')])}
I believe you are quite confused as to what it is you want to do and how to achieve it. Assuming I understood your question correctly, this is how I would do it:
from collections import OrderedDict
def info_from_row(my_dict):
try:
return float(my_dict['Duration'])
except KeyError:
return float(my_dict['Duration (min)'])
example_dict = {'X': OrderedDict([('ID', '123456'), ('Duration', '54941')]),
'Y': OrderedDict([('ID', '789101'), ('Duration (min)', '7869')])}
print(info_from_row(example_dict['X'])) # -> 54941.0
print(info_from_row(example_dict['Y'])) # -> 7869.0
As you can see, the duration is printed regardless of which subdictionary you wish to query.
Another way to do the exact same thing that does not use try-except is this:
def info_from_row(my_dict):
if 'Duration' in my_dict:
return float(my_dict['Duration'])
else:
return float(my_dict['Duration (min)'])
which has exactly the same outcome and is called in the exact same way; info_from_row(example_dict['Y']).
If you want the main key ('X' or 'Y') to be a function-argument as well, you can slightly modify the function (any of them) like so:
def info_from_row(my_dict, main_key):
if 'Duration' in my_dict[main_key]:
return float(my_dict[main_key]['Duration'])
else:
return float(my_dict[main_key]['Duration (min)'])
but then the call statements have to be modified as well:
print(info_from_row(example_dict, 'X')) # -> 54941.0
print(info_from_row(example_dict, 'Y')) # -> 7869.0

Define a dictionary name within a function

I am writing a function that will take a parameter and, among other things, make a dictionary. I would like the dictionary's name to be based off the name of the input file. Say ht input file is input.xml , i would like the name of the dictionary to be input. Ideally I would use something like this:
def function(input):
for x in y: list(get value)
input[:4][key] = [value]
I am wondering if you know a better way to do this but what i am using now is an extra name in the function:
def function(input, dictname):
for x in y: list(get value)
dictname[key] = [value]
right now I am simply adding a second name to my function but am wondering if there is a way to do this to require fewer inputs.
Edit
I am including a longer version of the function I am using so you guys can get the context. This uses a BioPython module to iterate through an XML file of hits. I am using [temp] to hold the hits for each query and then making a dictionary of for each set of query/hits. I would like this dictionary to be named the same as my input file.
from Bio.Blast import NCBIXML
def make_blast_dictionary(blastxml, maxhits, blastdict):
temp=[]
for record in NCBIXML.parse(open(blastxml):
for number, align in enumerate(record.alignments):
if number == int(maxhits): break
temp.append(str(align.title).split("|")[1])
blastdict[str(record.query_id)] = [temp]
The thing about named variables is that you can call them whatever you like. It's best to name them specific to the context you're using them with.
It would be a better move to simply return a dictionary from your method, instead.
The other respondents are legitimately concerned about why you would want to do this or whether you should do this. That being said, here is how you could do it:
import os.path
def function(filename):
d = {'red': 10, 'blue': 20}
name, ext = os.path.splitext(filename)
globals()[name] = d
function('input.xml')
print input
def make_name(input):
return = input.split('.')[0]
def function(input):
"""Note: this function is incomplete and assumes additional parameters are in your original script
"""
for x in y: list(get value)
dict_name[key] = [value]
return dict_name
def make_dict(input):
dict_name = make_name(input)
dict_name = {}
dict_name = function(input)
return dict_name
Is this what you need?

Categories

Resources