python call function in get method of dictionary instead default value - python

Need some help in order to understand some things in Python and get dictionary method.
Let's suppose that we have some list of dictionaries and we need to make some data transformation (e.g. get all names from all dictionaries by key 'name'). Also I what to call some specific function func(data) if key 'name' was not found in specific dict.
def func(data):
# do smth with data that doesn't contain 'name' key in dict
return some_data
def retrieve_data(value):
return ', '.join([v.get('name', func(v)) for v in value])
This approach works rather well, but as far a I can see function func (from retrieve_data) call each time, even key 'name' is present in dictionary.

If you want to avoid calling func if the dictionary contains the value, you can use this:
def retrieve_data(value):
return ', '.join([v['name'] if 'name' in v else func(v) for v in value])
The reason func is called each time in your example is because it gets evaluated before get even gets called.

Related

how to call the python function by passing the output of the function as input to the function

I need to write a python function call logic that calls the python function multiple times.
let's say for example I have a script test.py
I'm running the script like python test.py val
val=sys.argv[1]
def check(param, val):
.
.
.
if val == valid.text:
print '{:10s}:{:10}'.format(param, all.text)
values=os.walk(runtime).next()[1]
for param in values:
check(param, val)
so here the output like
driver 1.1
dmname 1.5-temp
fdrmenu 1.0-rem
so here I need to run the same function check(param, val) by taking the output as input for the function call.
the function calls like check(param, val) --> here val should be driver and so on for dmname , fdrmenu.
and call same function for output of driver, dmname and so on until we get the null for all the outputs.
here sys.srgv[1] should assign to val only for the first time, from next time it should be driver, dmname and so on.
Something recursively like this?
data={'driver':'1.1','dmname':'1.5-temp','fdrmenu':'1.0-rem'}
def check(data,key):
val = data.pop(key)
if type(val) == str:
print(key,val)
if data: check(data,list(data.keys())[0])
return None
check(data,list(data.keys())[0])
I'm not sure if I understand your question correctly so I don't know if I'm on the right track.
This function basically takes a dictionary (data) of elements of key/value pairs and you call it with the dictionary and its first key.
check(data,list(data.keys())[0])
Inside the function you extract the value associated to the key and delete the pair
val = data.pop(key)
So the dictionary started like
{'driver':'1.1','dmname':'1.5-temp','fdrmenu':'1.0-rem'}
the first key is 'driver' and the value is '1.1'. So now the variable val == '1.1' but the dictionary is now
{'dmname':'1.5-temp','fdrmenu':'1.0-rem'}
because the first key/value pair was deleted with the pop function
Then using the val you extracted you check a condition
if type(val) == str:
in this case val == '1.1' so it checks and then you print the key and the value which are 'driver' and '1.1'
then you check that the dictionary is not None and if it isn't you call the same function in the same way as before but since you deleted the first key/value pair from the dictionary the next first key/value element will be 'dmname':'1.5-temp'
{'dmname':'1.5-temp','fdrmenu':'1.0-rem'}
The next call the dictionary will be just one element
{'fdrmenu':'1.0-rem'}
and the last call the dictionary will be empty
{}
so the condition
if data
will not check and the function will return None
You could do something like this with pairs of params and values in your case if I understand your question correctly.
I modified the function to use the type of data you apparently have so the output of this function will be
driver 1.1
dmname 1.5-temp
fdrmenu 1.0-rem

Prevent evaluating default function in dictionary.get or dictionary.setdefault for existing keys

I'd like to keep track of key-value pairs I've processed already in a dictionary (or something else if it's better), where key is some input and value is the return output of some complex function/calculation. The main purpose is to prevent doing the same process over again if I wish to get the value for a key that has been seen before. I've tried using setdefault and get to solve this problem, but the function I call ends up getting executed regardless if the key exists in the dictionary.
Sample code:
def complex_function(some_key):
"""
Complex calculations using some_key
"""
return some_value
# Get my_key's value in my_dict. If my_key has not been seen yet,
# calculate its value and set it to my_dict[my_key]
my_value = my_dict.setdefault(my_key, complex_function(my_key))
complex_function ends up getting carried out regardless if my_key is in my_dict. I've also tried using my_dict.get(my_key, complex_function(my_key)) with the same result. For now, this is my fixed solution:
if my_key not in my_dict:
my_dict[my_key] = complex_function(my_key)
my_value = my_dict[my_key]
Here are my questions. First, is using a dictionary for this purpose the right approach? Second, am I using setdefault correctly? And third, is my current fix a good solution to the problem? (I end up calling my_dict[my_key] twice if my_key doesn't exist)
So I went ahead and took Vincent's suggestion of using a decorator.
Here's what the new fix looks like:
import functools
#functools.lru_cache(maxsize=16)
def complex_function(some_input):
"""
Complex calculations using some_input
"""
return some_value
my_value = complex_function(some_input)
From what I understand so far, lru_cache uses a dictionary to cache the results. The key in this dictionary refers to argument(s) to the decorated function (some_input) and the value refers to the return value of the decorated function (some_value). So, if the function gets called with an argument that's previously been passed before, it would simply return the value referenced in the decorator's dictionary instead of running the function. If the argument hasn't been seen, the function proceeds as normal, and in addition, the decorator creates a new key-value pair in its dictionary.
I set the maxsize to 16 for now as I don't expect some_input to represent more than 10 unique values. One thing to note is that the arguments for the decorated function are required to be non-mutable and hashable, as it uses the arguments as keys for its dictionary.
original_dict = {"a" : "apple", "b" : "banana", "c" : "cat"}
keys = a.keys()
new_dict = {}
For every key that you access now, run the following command :
new_dict[key] = value
To check if you have already accessed a key, run the following code :
#if new_key is not yet accessed
if not new_key in new_dict.keys() :
#read the value of new_key from original_dict and write to new_dict
new_dict[new_key] = original_dict[new_key]
I hope this helps
Your current solution is fine. You are creating slightly more work, but significantly reducing the computational workload when the key is already present.
However, defaultdict is almost what you need here. By modifying it a little bit we can make it work exactly as you want.
from collections import defaultdict
class DefaultKeyDict(defaultdict):
def __missing__(self, key):
if self.default_factory is None:
raise KeyError(key)
self[key] = value = self.default_factory(key)
return value
d = DefaultKeyDict(lambda key: key * 2)
assert d[1] == 2
print(d)

Unique constant reference

Let's take as an example the following code :
ALL = "everything"
my_dict = {"random":"values"}
def get_values(keys):
if keys is None:
return {}
if keys is ALL:
return my_dict
if not hasattr(keys, '__iter__')
keys = [keys]
return {key: my_dict[key] for key in keys}
The function get_values returns a dict with the given key, or keys if the parameter is an iterable, an empty dictionary if the parameter is None or the whole dictionary if the parameter is the constant ALL.
The problem with this happens when you would want to return a key called "everything". Python might use the same reference for ALL and the parameter (since they're both the same immutable), which would make the keys is ALL expression True. The function will therefore return the whole dict, so not the intended behavior.
It would be possible to assign ALL to an instance object of a class defined specifically for that purpose, or to use the type method to generate an object inline, which would make ALL a unique reference. Both solutions seem a little overkill though.
I could also use a flag in the function declaration (i.e. : def get_values(keys, all=False)), but then I can always derive the value of a parameter from the other (if all is True, then keys is None, if keys is not None, then All is not False), so it seems overly verbose.
What is your opinion on the previously mentioned techniques, and do you see other possible ways of fixing this ?
Don't use a value that could be (without extreme effort) a valid key as the sentinel.
ALL = object()
However, it seems much simpler to define the function to take a (possibly empty) sequence of keys.
def get_values(keys=None):
if keys is None:
keys = []
rv = {}
for key in keys:
# Keep in mind, this is a reference to
# an object in my_dict, not a copy. Also,
# you may want to handle keys not found in my_dict:
# ignore them, or set rv[key] to None?
rv[key] = my_dict[key]
return rv
d1 = get_all_values() # Empty dict
d2 = get_all_values([]) # Explicitly empty dict
d3 = get_all_values(["foo", "bar"]) # (Sub)set of values
d4 = get_all_values(my_dict) # A copy of my_dict
In the last case, we take advantage of the fact that get_all_values can take any iterable, and an iterator over a dict iterates over its keys.

How to save 'arrays' to variable from QueryDict

I have a following structure of QueryDict:
QueryDict: {u'tab[1][val1]': [u'val1'], u'tab[1][val2]': [u'val2'], u'tab[0][val1]': [u'val1'], u'tab[1][val2]': [u'val2']}
I want to store it in an iterable variable so I can do something like this:
for x in xs:
do_something(x.get('val1'))
where x is tab[0] etc
I tried:
dict(request.POST._iteritems())
but it doesn't return tab[0] but tab[0][val1] as an element.
Is it possible to store entire tab[idx] in variable?
Django's QueryDict has a few additional methods to deal with multiple values per key compared to the traditional dict; useful for your purposes are:
QueryDict.iterlists() Like QueryDict.iteritems() except it includes
all values, as a list, for each member of the dictionary.
QueryDict.getlist(key, default)
Returns the data with the requested key, as a Python list. Returns an empty list if the key doesn’t exist and no default value was provided. It’s guaranteed to return a list of some sort unless the default value was no list.
QueryDict.lists()
Like items(), except it includes all values, as a list, for each member of the dictionary.
So you can do something like:
qd = QueryDict(...)
for values in qd.lists():
for value in values:
do_something(value)
Also note that the "normal" dict methods like get always return only a single value (the last value for that key).

Dictionary object to decision tree in Pydot

I have a dictionary object as such:
menu = {'dinner':{'chicken':'good','beef':'average','vegetarian':{'tofu':'good','salad':{'caeser':'bad','italian':'average'}},'pork':'bad'}}
I'm trying to create a graph (decision tree) using pydot with the 'menu' data this.
'Dinner' would be the top node and its values (chicken, beef, etc.) are below it. Referring to the link, the graph function takes two parameters; a source and a node.
It would look something like this:
Except 'king' would be 'dinner' and 'lord' would be 'chicken', 'beef', etc.
My question is: How do I access a key in a value? To create a tree from this data I feel like I need to create a loop which checks if there is a value for a specific key and plots it. I'm not sure how to call values for any dictionary object (if it's not necessarily called 'dinner' or have as many elements.).
Any suggestions on how to graph it?
Using a recursive function
You might want to consider using a recursive function (like the visit in my code below), so that you are able to process a general nested dictionary. In this function, you want to pass a parent parameter to keep track of who is your incoming node. Also note you use isinstance to check if the dictionary value of a key is a dictionary of its own, in that case you need to call your visit recursively.
import pydot
menu = {'dinner':
{'chicken':'good',
'beef':'average',
'vegetarian':{
'tofu':'good',
'salad':{
'caeser':'bad',
'italian':'average'}
},
'pork':'bad'}
}
def draw(parent_name, child_name):
edge = pydot.Edge(parent_name, child_name)
graph.add_edge(edge)
def visit(node, parent=None):
for k,v in node.iteritems():# If using python3, use node.items() instead of node.iteritems()
if isinstance(v, dict):
# We start with the root node whose parent is None
# we don't want to graph the None node
if parent:
draw(parent, k)
visit(v, k)
else:
draw(parent, k)
# drawing the label using a distinct name
draw(k, k+'_'+v)
graph = pydot.Dot(graph_type='graph')
visit(menu)
graph.write_png('example1_graph.png')
Resulting tree structure
Your question isn't entirely clear to me, but the way of accessing a dictionary key's value in Python is simply:
dictionary[key]
That will return to you that key's value. If that key is not in the dictionary, it will return a KeyError, so if you are working with dictionaries and you're not sure if the key you're requesting will be in the dictionary, you have two options.
If-statement (preferred):
if key in dictionary:
return dictionary[key]
Try-catch:
try:
return dictionary[key]
except KeyError:
pass
If you don't know the keys in your dictionary and you need to get them, you can simply call dictionary.keys() and it will return a list of all of the keys in the dictionary.
Getting a the value of a dictionary key will return an object that could even be another object. Thus, to find out the value of "tofu", for example, we'd do the following:
menu['dinner']['vegetarian']['tofu']
# returns value 'good'

Categories