Changing value for non-valid key without using an if Statement - python-3.x

Here is my task:
Write a function get_value(dictionary, key) which returns the value for the given key in the given dictionary, using the get method. If the key is not valid, your function should return -1.
I have written a function which assesses a dictionary using a get function and the code work just fine. However, I need a way to return a value of -1 of the key is not valid instead of returning "Not a Key". I have been requested to solve this issue without the use of an if statement. Here is my current code:
def get_value(dictionary, key):
for key in key.split("."):
dictionary.get(key)
dictionary = dictionary[key]
return dictionary
Thanks in advance.

Related

When a particular key is not present in a dictionary

From a Dictionary input_dict={'Name': 'Monty', 'Profession': 'Singer' }, get the value of a key Label which is not a part of the dictionary, in such a way that Python doesn't hit an error. If the key does not exist in the dictionary, Python should return NA.
Sample Input:
{'Name': 'Monty', 'Profession': 'Singer' }
Sample Output:
NA
The get() method is really useful here as it returns none and don't break the system by giving error
You can use get method of the dictionary. This method never raises a KeyError.
input_dict.get('Label', 'NA')
The syntax of get() is:
dict.get(key, value)
get() Parameters
The get() method takes maximum of two parameters:
key - key to be searched in the dictionary
value (optional) - Value to be returned if the key is not found. The
default value is None.
The get() method returns:
the value for the specified key if key is in dictionary.
None if the key is not found and value is not specified.
value if the key is not found and value is specified.
import ast,sys
input_str = sys.stdin.read()
input_dict = ast.literal_eval(input_str)
answer=input_dict.get('Label', 'NA')
print(answer)
Final solution can be with use of Get().
import ast, sys
input_str = sys.stdin.read()
input_dict = ast.literal_eval(input_str)
answer = input_dict.get('Label', 'NA')
print(answer)
It is working fine
We use update statement to update the Label and so when call the label, we the value of "NA"
import ast,sys
input_str = sys.stdin.read()
input_dict = ast.literal_eval(input_str)
input_dict.update({'Label':'NA'})
answer=input_dict["Label"]
print(answer)
import ast,sys
input_str = sys.stdin.read()
input_dict = ast.literal_eval(input_str)
input_dict["Label"]="NA"
answer=input_dict["Label"]
# Type your answer here
print(answer)

Changing the values in a dict, changes the values of the original returned dict

def data_query(Chan, Mode, Format, Sampling, Wave_Data):
if Mode.get_state() == 'NORM':
if Chan.get_state() == 'CHAN1':
wave_dict = Wave_Data.get_wave_data(1)
if Format.get_state() == 'ASCII':
return wave_dict
elif Format.get_state() == 'BYTE':
for i in range(0, len(wave_dict)):
wave_dict[i] = bin(int(wave_dict[i]))
return wave_dict
So in the code above, the parameter 'Wave_Data' is an instance of another class which holds the value of a dict 'self.wave1' which is returned by the function 'get_wave_data'.
def get_wave_data(self, channel=1):
if channel == 1:
return self.wave1
elif channel == 2:
pass
My problem is that in the code above when I make changes to the values in the local dict - 'wave_dict' (i.e. convert the values to binary), it also the changes the values in self.wave1. If I understand this correctly, its acting as a pointer to the self.wave1 object (which I am streaming using udp sockets via another thread) rather than a normal local variable.
Btw, the first code block is a function in the main thread and the second code block is a function in a class that is running as a daemon thread, the instance of which is also passed in the 'data_query' function.
Any help would be appreciated. Sorry if I've used wrong terminology anywhere.
I fixed this by creating an array and appending the hex(dict values) to this array, then returning the array instead of the dict.
Then I handle this on the receiving end by try-except to accept either a dict or a list:
try:
Wdata = list(Wdata_dict.values())
except:
Wdata = Wdata_dict

Turning if statement into a single line while setting a variable [duplicate]

I need a way to get a dictionary value if its key exists, or simply return None, if it does not.
However, Python raises a KeyError exception if you search for a key that does not exist. I know that I can check for the key, but I am looking for something more explicit. Is there a way to just return None if the key does not exist?
You can use dict.get()
value = d.get(key)
which will return None if key is not in d. You can also provide a different default value that will be returned instead of None:
value = d.get(key, "empty")
Wonder no more. It's built into the language.
>>> help(dict)
Help on class dict in module builtins:
class dict(object)
| dict() -> new empty dictionary
| dict(mapping) -> new dictionary initialized from a mapping object's
| (key, value) pairs
...
|
| get(...)
| D.get(k[,d]) -> D[k] if k in D, else d. d defaults to None.
|
...
Use dict.get
Returns the value for key if key is in the dictionary, else default. If default is not given, it defaults to None, so that this method never raises a KeyError.
You should use the get() method from the dict class
d = {}
r = d.get('missing_key', None)
This will result in r == None. If the key isn't found in the dictionary, the get function returns the second argument.
If you want a more transparent solution, you can subclass dict to get this behavior:
class NoneDict(dict):
def __getitem__(self, key):
return dict.get(self, key)
>>> foo = NoneDict([(1,"asdf"), (2,"qwerty")])
>>> foo[1]
'asdf'
>>> foo[2]
'qwerty'
>>> foo[3] is None
True
I usually use a defaultdict for situations like this. You supply a factory method that takes no arguments and creates a value when it sees a new key. It's more useful when you want to return something like an empty list on new keys (see the examples).
from collections import defaultdict
d = defaultdict(lambda: None)
print d['new_key'] # prints 'None'
A one line solution would be:
item['key'] if 'key' in item else None
This is useful when trying to add dictionary values to a new list and want to provide a default:
eg.
row = [item['key'] if 'key' in item else 'default_value']
As others have said above, you can use get().
But to check for a key, you can also do:
d = {}
if 'keyname' in d:
# d['keyname'] exists
pass
else:
# d['keyname'] does not exist
pass
You could use a dict object's get() method, as others have already suggested. Alternatively, depending on exactly what you're doing, you might be able use a try/except suite like this:
try:
<to do something with d[key]>
except KeyError:
<deal with it not being there>
Which is considered to be a very "Pythonic" approach to handling the case.
For those using the dict.get technique for nested dictionaries, instead of explicitly checking for every level of the dictionary, or extending the dict class, you can set the default return value to an empty dictionary except for the out-most level. Here's an example:
my_dict = {'level_1': {
'level_2': {
'level_3': 'more_data'
}
}
}
result = my_dict.get('level_1', {}).get('level_2', {}).get('level_3')
# result -> 'more_data'
none_result = my_dict.get('level_1', {}).get('what_level', {}).get('level_3')
# none_result -> None
WARNING: Please note that this technique only works if the expected key's value is a dictionary. If the key what_level did exist in the dictionary but its value was a string or integer etc., then it would've raised an AttributeError.
I was thrown aback by what was possible in python2 vs python3. I will answer it based on what I ended up doing for python3. My objective was simple: check if a json response in dictionary format gave an error or not. My dictionary is called "token" and my key that I am looking for is "error". I am looking for key "error" and if it was not there setting it to value of None, then checking is the value is None, if so proceed with my code. An else statement would handle if I do have the key "error".
if ((token.get('error', None)) is None):
do something
You can use try-except block
try:
value = dict['keyname']
except IndexError:
value = None
d1={"One":1,"Two":2,"Three":3}
d1.get("Four")
If you will run this code there will be no 'Keyerror' which means you can use 'dict.get()' to avoid error and execute your code
If you have a more complex requirement that equates to a cache, this class might come in handy:
class Cache(dict):
""" Provide a dictionary based cache
Pass a function to the constructor that accepts a key and returns
a value. This function will be called exactly once for any key
required of the cache.
"""
def __init__(self, fn):
super()
self._fn = fn
def __getitem__(self, key):
try:
return super().__getitem__(key)
except KeyError:
value = self[key] = self._fn(key)
return value
The constructor takes a function that is called with the key and should return the value for the dictionary. This value is then stored and retrieved from the dictionary next time. Use it like this...
def get_from_database(name):
# Do expensive thing to retrieve the value from somewhere
return value
answer = Cache(get_from_database)
x = answer(42) # Gets the value from the database
x = answer(42) # Gets the value directly from the dictionary
If you can do it with False, then, there's also the hasattr built-in funtion:
e=dict()
hasattr(e, 'message'):
>>> False

Python calling mock with "=" not called result

I am trying to mock the following call:
df_x = method() # returns a pandas dataframe
df_x.loc[df_x['atr'] < 0, 'atr'] = 0
I have mocked the method so it returns a MagicMock and set a default value to the __ getitem__ attribute of the MagicMock as like this:
mock_df_x = mock_method.return_value
mock_df_x.__getitem__.return_value = 0
The problem is when I try asserting the call:
mock_df_x.loc.__getitem__.assert_called_with(False, 'atr')
I get a function not called error. If I call the function like this without the "= 0" part the assertion works.
df_x.loc[df_x['atr'] < 0, 'atr']
The reason you are seeing this different behavior depending on whether on you have = 0 at the end of the call you are testing is that in Python's data model, those correspond to two different magic methods: __getitem__ and __setitem__.
This makes sense, because for example doing some_dictionary['nonexistent_key]' raises KeyError, whereas some_dictionary['nonexistent_key]' = 1 doesn't, and sets the value as expected.
Now, in order to fix your test, you only need to change your assertion from:
mock_df_x.loc.__getitem__.assert_called_with((False, 'atr'))
which only works if you are accessing the key, to:
mock_df_x.loc.__setitem__.assert_called_with((False, 'atr'), 0)
which works if you are trying to assign a value to that key.
Notice the extra parameter, too, corresponding to the value you are actually trying to assign.

AWS Lambda Python 3 check event variable exists

try:
event['ids']
except NameError:
ids = None
This is throwing a KeyError. I just want to check if the event variable exists and set to none or pass the value if it does.
I have also tried to use
if (len(event['ids']) < 1)
but get an error.
Am I missing something? I may or may not have all my event keys passed and want to check for existence.
Use the get method. The second parameter is the default value if the key doesn't exist in the dictionary. It's the standard way to get values from a dictionary when you're not sure if the key exists and you don't want an exception.
ids = event.get('ids', None)
We can check if the key 'key1' exists in the Json dictionary.
{
"key1":"value1"
}
To retrieve the value 'value1' if the key 'key1' exists in the dictionary.
if event.get('key1',None) != None:
value = event.get('key1',None)

Resources