When a particular key is not present in a dictionary - python-3.x

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)

Related

How to convert python dict to DictRow object

Hi I am writing unittest using pytest. But I am not able to mock few db functions. We are using psycopg2 for db connections and executions. Response of query returned from psycopg2 is of the type DictRow which can be accessed either by key or by index.
Ex:
response = ['prajwal', '23', 'engineer'] #Response of a query "select name, age , job from users"
>>>response[0]
'prajwal'
>>>response['name']
'prajwal'
I want to know is there any way by which we can covert dict/list to above mentioned type.
Looking at the source for psycopg2, creating a DictRow requires passing in a DictCursor object. However the only thing it uses from DictCursor appears to be an index and description attribute.
# found in lib\site-packages\psycopg2.extras.py
class DictRow(list):
"""A row object that allow by-column-name access to data."""
__slots__ = ('_index',)
def __init__(self, cursor):
self._index = cursor.index
self[:] = [None] * len(cursor.description)
The index looks like a dict with a mapping a key to an index. e.g.response['name'] = 0
The description looks like your dict that you want to convert.
If you're feeling hacky you could take advantage of duck typing and pretend you're passing in a cursor when you're just satisfying the requirements.
The only caveat is after we instantiate the DictRow, we need to populate it. Our fake cursor hack will take care of the rest.
from psycopg2.extras import DictRow
class DictRowHack:
def __init__(self, my_dict):
# we need to set these 2 attributes so that
# it auto populates our indexes
self.index = {key: i for i, key in enumerate(my_dict)}
self.description = my_dict
def dictrow_from_dict(my_dict):
# this is just a little helper function
# so you don't always need to go through
# the steps to recreate a DictRow
fake_cursor = DictRowHack(my_dict)
my_dictrow = DictRow(fake_cursor)
for k, v in my_dict.items():
my_dictrow[k] = v
return my_dictrow
response = {'name': 'prajwal', 'age': '23', 'job': 'engineer'}
my_dictrow = dictrow_from_dict(response)
print(my_dictrow[1])
print(my_dictrow['name'])
print(type(my_dictrow))

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

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)

Passing string variable value in Pandas dataframe

I have been trying to use variables for passing the string value in dataframe for various column operations, but the code is giving me wrong results. See the code below, I am using in Jupyter Notebook:
first_key = input("key 1: ")
second_key = input("ket 2: ")
third_key = input("ket 2: ")
These receive the values "Russia", "China", "Trump" for the operation in next cell as below:
tweets['{first_key}'] = tweets['text'].str.contains(r"^(?=.*\b{first_key}\b).*$", case=False) == True
tweets['{second_key}'] = tweets['text'].str.contains(r"^(?=.*\b'{second_key}'\b).*$", case=False) == True
tweets['{third_key}'] = tweets['text'].str.contains(r"^(?=.*\b'{third_key}'\b).*$", case=False) == True
But results are wrong. Any idea how to get the correct results. A small snapshot of the results is like this.
I've tried cleaning up your code. You can leverage f-strings (using python-3.6+) with a tiny change to your code:
def contains(series, key):
return series.str.contains(rf"^(?=.*\b{key}\b).*$", case=False)
If you're working with an older version of python, use str.format:
def contains(series, key):
return series.str.contains(r"^(?=.*\b{}\b).*$".format(key), case=False)
Next, call this function inside a loop:
for key in (first_key, second_key, third_key):
tweets[key] = contains(tweets['text'], key)

python string format suppress/silent keyerror/indexerror [duplicate]

This question already has answers here:
How to get Python to gracefully format None and non-existing fields [duplicate]
(3 answers)
Closed 8 years ago.
Is there a way to use python string.format such that no exception is thrown when an index is missing, instead an empty string is inserted.
result = "i am an {error} example string {error2}".format(hello=2,error2="success")
here,result should be :
"i am an example string success"
Right now, python throws a keyerror and stops formatting. Is it possible to change this behavior ?
Thanks
Edit:
There exists Template.safe_substitute (even that leaves the pattern intact instead of inserting an empty string) , but couldn't something similar for string.format
The desired behavior would be similar to string substitution in php.
class Formatter(string.Formatter):
def get_value(self,key,args,kwargs):
try:
if hasattr(key,"__mod__"):
return args[key]
else:
return kwargs[key]
except:
return ""
This seems to provide the desired behavior.
The official solution (Python 3 Docs) for strings in format mappings is to subclass the dict class and to define the magic-method __missing__(). This method is called whenever a key is missing, and what it returns is used for the string formatting instead:
class format_dict(dict):
def __missing__(self, key):
return "..."
d = format_dict({"foo": "name"})
print("My %(foo)s is %(bar)s" % d) # "My name is ..."
print("My {foo} is {bar}".format(**d)) # "My name is ..."
Edit: the second print() works in Python 3.5.3, but it does not in e.g. 3.7.2: KeyError: 'bar' is raised and I couldn't find a way to catch it.
After some experiments, I found a difference in Python's behavior. In v3.5.3, the calls are __getitem__(self, "foo") which succeeds and __getitem__(self, "bar") which can not find the key "bar", therefore it calls __missing__(self, "bar") to handle the missing key without throwing a KeyError. In v3.7.2, __getattribute__(self, "keys") is called internally. The built-in keys() method is used to return an iterator over the keys, which yields "foo", __getitem__("foo") succeeds, then the iterator is exhausted. For {bar} from the format string there is no key "bar". __getitem__() and hence __missing_() are not called to handle the situation. Instead, the KeyError is thrown. I don't know how one could catch it, if at all.
In Python 3.2+ you should use format_map() instead (also see Python Bug Tracker - Issue 6081):
from collections import defaultdict
d = defaultdict(lambda: "...")
d.update({"foo": "name"})
print("My {foo} is {bar}".format_map(d)) # "My name is ..."
If you want to keep the placeholders, you can do:
class Default(dict):
def __missing__(self, key):
return key.join("{}")
d = Default({"foo": "name"})
print("My {foo} is {bar}".format_map(d)) # "My name is {bar}"
As you can see, format_map() does call __missing__().
The following appears to be the most compatible solution as it also works in older Python versions including 2.x (I tested v2.7.15):
class Default(dict):
def __missing__(self, key):
return key.join("{}")
d = Default({"foo": "name"})
import string
print(string.Formatter().vformat("My {foo} is {bar}", (), d)) # "My name is {bar}"
To keep placeholders as-is including the format spec (e.g. {bar:<15}) the Formatter needs to be subclassed:
import string
class Unformatted:
def __init__(self, key):
self.key = key
def __format__(self, format_spec):
return "{{{}{}}}".format(self.key, ":" + format_spec if format_spec else "")
class Formatter(string.Formatter):
def get_value(self, key, args, kwargs):
if isinstance(key, int):
try:
return args[key]
except IndexError:
return Unformatted(key)
else:
try:
return kwargs[key]
except KeyError:
return Unformatted(key)
f = Formatter()
s1 = f.vformat("My {0} {1} {foo:<10} is {bar:<15}!", ["real"], {"foo": "name"})
s2 = f.vformat(s1, [None, "actual"], {"bar":"Geraldine"})
print(s1) # "My real {1} name is {bar:<15}!"
print(s2) # "My real actual name is Geraldine !"
Note that the placeholder indices are not changed ({1} remains in the string without a {0}), and in order to substitute {1} you need to pass an array with any odd first element and what you want to substitute the remaining placeholder with as second element (e.g. [None, "actual"]).
You can also call the format() method with positional and named arguments:
s1 = f.format("My {0} {1} {foo:<10} is {bar:<15}!", "real", foo="name")
s2 = f.format(s1, None, "actual", bar="Geraldine")
str.format() doesn't expect a mapping object. Try this:
from collections import defaultdict
d = defaultdict(str)
d['error2'] = "success"
s = "i am an {0[error]} example string {0[error2]}"
print s.format(d)
You make a defaultdict with a str() factory that returns "". Then you make one key for the defaultdict. In the format string, you access keys of the first object passed. This has the advantage of allowing you to pass other keys and values, as long as your defaultdict is the first argument to format().
Also, see http://bugs.python.org/issue6081
Unfortunately, no, there is no such way to do by default. However you can provide it defaultdict or object with overridden __getattr__, and use like this:
class SafeFormat(object):
def __init__(self, **kw):
self.__dict = kw
def __getattr__(self, name):
if not name.startswith('__'):
return self.__dict.get(name, '')
print "i am an {0.error} example string {0.error2}".format(SafeFormat(hello=2,error2="success"))
i am an example string success
I made a version that does work similarly to Daniel's method but without the {0.x} attribute access.
import string
class SafeFormat(object):
def __init__(self, **kw):
self.__dict = kw
def __getitem__(self, name):
return self.__dict.get(name, '{%s}' % name)
string.Formatter().vformat('{what} {man}', [], SafeFormat(man=2))
prints out
'{what} 2'

Resources