When initializing a dictionary with d = {} Pycharm's code inspector generates a warning, saying
This dictionary creation could be rewritten as a dictionary literal.
If I rewrite it d = dict() the warning goes away. Since {} already is a dictionary literal, I'm pretty sure the message is erroneous. Furthermore, it seems like both d = {} and d = dict() are valid and Pythonic.
This related question seems to conclude that the choice is just a matter of style/preference:
differences between "d = dict()" and "d = {}"
Why would Pycharm complain about d = {}?
UPDATE:
Mac nailed it. The warning actually applied to multiple lines, not just the one that was flagged.
Pycharm seems to look for a sequence of consecutive statements where you initialize a dictionary and then set values in the dictionary. For example, this will trigger the warning:
d = {}
d['a'] = 1
But this code will not:
d = {}
pass
d['a'] = 1
What is the code following your dictionary declaration?
I think PyCharm will trigger the error if you have something like:
dic = {}
dic['aaa'] = 5
as you could have written
dic = {'aaa': 5}
Note: The fact that the error goes away if you use the function dict(). This doesn't necessarily mean that pycharm believes dict() is a literal. It could just mean that it doesn't complain about it:
dic = dict()
dic['aaa'] = 5
This can be disabled in the Project Settings or Default Settings.
Navigate to Settings -> Inspections -> Python
Uncheck "Dictionary creation could be rewritten by dictionary literal"
for those who like (just like me) to initialize dictionaries with single operation
d = {
'a': 12,
'b': 'foo',
'c': 'bar'
}
instead of many lines like
d = dict()
d['a'] = 12
d['b'] = ....
in the end I ended up with this:
d = dict()
d.update({
'a': 12,
'b': 'foo',
'c': 'bar'
})
Pycharm is not complaining on this
mydict = {
a: 5,
b:z+c/2
}
The dictionary could have been created directly without initialising them first and then reassigning new values.
I have a situation where this warning is bugging the hell out of me. In my case, I'm populating my dict partially as literals and partially from a tuple output by a function, like so:
def get_other_values():
return 3, 4
foo = {
"a": 1,
"b": 2
}
foo["c"], foo["d"] = get_other_values()
So, unless I create interim vars for the output of get_other_values, PEP8 generates this warning even though I'm creating the dict with literals. And I can't assign the c and d keys in the literal, since the values are output as a tuple.
Related
When I use
a = {}
and
a = set()
And sometimes I see use like:
a = set([])
Are they the same? What's the difference between them?
I am asking because
a = set(range(5))
b = {0,1,2,3,4}
a == b
>>> True
By default {} means an empty dictionary in python. However, the curly braces are used for both dict and set literals, see the following examples:
empty_set = set()
non_empty_set = {1,2,3}
empty_dict = {}
empty_dict2 = dict()
non_empty_dict = {"a": 1}
avoid using
a = set([]) # instead use a = set()
When you initialise the variable with empty brackets it will be of type dict:
a = {}
print(f"type of a={type(a)}")
Output:
type of a=<class 'dict'>
However, if you initialise it with some values python will detect the type itself.
b = {1, 2, 3}
print(f"type of b={type(b)}")
c = {"some_key": "some_value"}
print(f"type of c={type(c)}")
Output:
type of b=<class 'set'>
type of c=<class 'dict'>
A set and a dictionary are two different data structures. You can read more about them here: Beginner to python: Lists, Tuples, Dictionaries, Sets
The literal {} will be a dictionary with key and value pairs, while set() is a set that contains just pure values. When using more than 0 elements, their literals will be distinguished by whether you include the key value pairs. For example, {1: 'a', 2: 'b'} vs {1, 2}.
They are not the same.
{} creates and empty dictionary (but {1,2,3} creates a set with 3 elements: 1, 2, 3)
set() creates a empty set
This question already has answers here:
Elegant way to unpack limited dict values into local variables in Python
(5 answers)
Closed 9 months ago.
Is there a Pythonic way to assign the values of a dictionary to its keys, in order to convert the dictionary entries into variables?
I tried this out:
>>> d = {'a':1, 'b':2}
>>> for key,val in d.items():
exec('exec(key)=val')
exec(key)=val
^
SyntaxError: invalid syntax
I am certain that the key-value pairs are correct because they were previously defined as variables by me before. I then stored these variables in a dictionary (as key-value pairs) and would like to reuse them in a different function. I could just define them all over again in the new function, but because I may have a dictionary with about 20 entries, I thought there may be a more efficient way of doing this.
You can do it in a single line with:
>>> d = {'a': 1, 'b': 2}
>>> locals().update(d)
>>> a
1
However, you should be careful with how Python may optimize locals/globals access when using this trick.
Note
I think editing locals() like that is generally a bad idea. If you think globals() is a better alternative, think it twice! :-D
Instead, I would rather always use a namespace.
With Python 3 you can:
>>> from types import SimpleNamespace
>>> d = {'a': 1, 'b': 2}
>>> n = SimpleNamespace(**d)
>>> n.a
1
If you are stuck with Python 2 or if you need to use some features missing in types.SimpleNamespace, you can also:
>>> from argparse import Namespace
>>> d = {'a': 1, 'b': 2}
>>> n = Namespace(**d)
>>> n.a
1
If you are not expecting to modify your data, you may as well consider using collections.namedtuple, also available in Python 3.
This was what I was looking for:
>>> d = {'a':1, 'b':2}
>>> for key,val in d.items():
exec(key + '=val')
You already have a perfectly good dictionary. Just use that. If you know what the keys are going to be, and you're absolutely sure this is a reasonable idea, you can do something like
a, b = d['a'], d['b']
but most of the time, you should just use the dictionary. (If using the dictionary is awkward, you are probably not organizing your data well; ask for help reorganizing it.)
you can use operator.itemgetter
>>> from operator import itemgetter
>>> d = {'a':1, 'b':2}
>>> a, b = itemgetter('a', 'b')(d)
>>> a
1
>>> b
2
Consider the "Bunch" solution in Python: load variables in a dict into namespace. Your variables end up as part of a new object, not locals, but you can treat them as variables instead of dict entries.
class Bunch(object):
def __init__(self, adict):
self.__dict__.update(adict)
d = {'a':1, 'b':2}
vars = Bunch(d)
print vars.a, vars.b
Python has great support for list unpacking, but not dict or object unpacking. The most unsurprising and Pythonic approach seems to be accessing each item by hand to build an intermediate tuple as described in this answer:
a, b = d['a'], d['b']
However, if you have a lot of properties, or variable names are long, it can get nasty to do:
great, wow, awesome = dictionary['great'], dictionary['wow'], dictionary['awesome']
For context, the JavaScript equivalent of the above (destructuring) is:
const {great, wow, awesome} = dictionary;
Here's an option that is a bit more dynamic:
>>> dictionary = dict(great=0, wow=1, awesome=2)
>>> great, wow, awesome = (dictionary[k] for k in ("great", "wow", "awesome"))
>>> great
0
>>> awesome
2
This is still verbose; you could write a function to abstract things a bit, but unfortunately you still have to type everything twice:
>>> def unpack(dct, *keys):
... return (dct[k] for k in keys)
...
>>> dictionary = dict(great=0, wow=1, awesome=2)
>>> great, wow, awesome = unpack(dictionary, "great", "wow", "awesome")
You can generalize this to work on objects too:
>>> def unpack(x, *keys):
... if isinstance(x, dict):
... return (x[k] for k in keys)
... return (getattr(x, k) for k in keys)
...
>>> from collections import namedtuple
>>> Foo = namedtuple("Foo", "a b c d e")
>>> foo = Foo(a=0, b=1, c=2, d=3, e=4)
>>> c, b, d, a = unpack(foo, "c", "b", "d", "a")
>>> d
3
After all is said and done, unpacking by hand on multiple lines is probably best for real production code that you need to be safe and comprehensible:
>>> great = dictionary["great"]
>>> wow = dictionary["wow"]
>>> awesome = dictionary["awesome"]
Use pandas:
import pandas as pd
var=pd.Series({'a':1, 'b':2})
#update both keys and variables
var.a=3
print(var.a,var['a'])
Many SO posts show you how to efficiently check the existence of a key in a dictionary, e.g., Check if a given key already exists in a dictionary
How do I do this for a multi level key? For example, if d["a"]["b"] is a dict, how can I check if d["a"]["b"]["c"]["d"] exists without doing something horrendous like this:
if "a" in d and isInstance(d["a"], dict) and "b" in d["a"] and isInstance(d["a"]["b"], dict) and ...
Is there some syntax like
if "a"/"b"/"c"/"d" in d
What I am actually using this for: we have jsons, parsed into dicts using simplejson, that I need to extract values from. Some of these values are nested three and four levels deep; but sometimes the value doesn't exist at all. So I wanted something like:
val = None if not d["a"]["b"]["c"]["d"] else d["a"]["b"]["c"]["d"] #here d["a"]["b"] may not even exist
EDIT: prefer not to crash if some subkey exists but is not a dictionary, e.g, d["a"]["b"] = 5.
Sadly, there isn't any builtin syntax or a common library to query dictionaries like that.
However, I believe the simplest(and I think it's efficient enough) thing you can do is:
d.get("a", {}).get("b", {}).get("c")
Edit: It's not very common, but there is: https://github.com/akesterson/dpath-python
Edit 2: Examples:
>>> d = {"a": {"b": {}}}
>>> d.get("a", {}).get("b", {}).get("c")
>>> d = {"a": {}}
>>> d.get("a", {}).get("b", {}).get("c")
>>> d = {"a": {"b": {"c": 4}}}
>>> d.get("a", {}).get("b", {}).get("c")
4
This isn't probably a good idea and I wouldn't recommend using this in prod. However, if you're just doing it for learning purposes then the below might work for you.
def rget(dct, keys, default=None):
"""
>>> rget({'a': 1}, ['a'])
1
>>> rget({'a': {'b': 2}}, ['a', 'b'])
2
"""
key = keys.pop(0)
try:
elem = dct[key]
except KeyError:
return default
except TypeError:
# you gotta handle non dict types here
# beware of sequences when your keys are integers
if not keys:
return elem
return rget(elem, keys, default)
UPDATE: I ended up writing my own open-source, pippable library that allows one to do this: https://pypi.python.org/pypi/dictsearch
A non-recursive version, quite similar to #Meitham's solution, which does not mutate the looked-for key. Returns True/False if the exact structure is present in the source dictionary.
def subkey_in_dict(dct, subkey):
""" Returns True if the given subkey is present within the structure of the source dictionary, False otherwise.
The format of the subkey is parent_key:sub_key1:sub_sub_key2 (etc.) - description of the dict structure, where the
character ":" is the delemiter.
:param dct: the dictionary to be searched in.
:param subkey: the target keys structure, which should be present.
:returns Boolean: is the keys structure present in dct.
:raises AttributeError: if subkey is not a string.
"""
keys = subkey.split(':')
work_dict = dct
while keys:
target = keys.pop(0)
if isinstance(work_dict, dict):
if target in work_dict:
if not keys: # this is the last element in the input, and it is in the dict
return True
else: # not the last element of subkey, change the temp var
work_dict = work_dict[target]
else:
return False
else:
return False
The structure that is checked is in the form parent_key:sub_key1:sub_sub_key2, where the : char is the delimiter. Obviously - it will match case-sensitively, and will stop (return False) if there's a list within the dictionary.
Sample usage:
dct = {'a': {'b': {'c': {'d': 123}}}}
print(subkey_in_dict(dct, 'a:b:c:d')) # prints True
print(subkey_in_dict(dct, 'a:b:c:d:e')) # False
print(subkey_in_dict(dct, 'a:b:d')) # False
print(subkey_in_dict(dct, 'a:b:c')) # True
This is what I usually use
def key_in_dict(_dict: dict, key_lookup: str, separator='.'):
"""
Searches for a nested key in a dictionary and returns its value, or None if nothing was found.
key_lookup must be a string where each key is deparated by a given "separator" character, which by default is a dot
"""
keys = key_lookup.split(separator)
subdict = _dict
for k in keys:
subdict = subdict[k] if k in subdict else None
if subdict is None: break
return subdict
Returns the key if exists, or None it it doesn't
key_in_dict({'test': {'test': 'found'}}, 'test.test') // 'found'
key_in_dict({'test': {'test': 'found'}}, 'test.not_a_key') // None
This question already has answers here:
Elegant way to unpack limited dict values into local variables in Python
(5 answers)
Closed 9 months ago.
Is there a Pythonic way to assign the values of a dictionary to its keys, in order to convert the dictionary entries into variables?
I tried this out:
>>> d = {'a':1, 'b':2}
>>> for key,val in d.items():
exec('exec(key)=val')
exec(key)=val
^
SyntaxError: invalid syntax
I am certain that the key-value pairs are correct because they were previously defined as variables by me before. I then stored these variables in a dictionary (as key-value pairs) and would like to reuse them in a different function. I could just define them all over again in the new function, but because I may have a dictionary with about 20 entries, I thought there may be a more efficient way of doing this.
You can do it in a single line with:
>>> d = {'a': 1, 'b': 2}
>>> locals().update(d)
>>> a
1
However, you should be careful with how Python may optimize locals/globals access when using this trick.
Note
I think editing locals() like that is generally a bad idea. If you think globals() is a better alternative, think it twice! :-D
Instead, I would rather always use a namespace.
With Python 3 you can:
>>> from types import SimpleNamespace
>>> d = {'a': 1, 'b': 2}
>>> n = SimpleNamespace(**d)
>>> n.a
1
If you are stuck with Python 2 or if you need to use some features missing in types.SimpleNamespace, you can also:
>>> from argparse import Namespace
>>> d = {'a': 1, 'b': 2}
>>> n = Namespace(**d)
>>> n.a
1
If you are not expecting to modify your data, you may as well consider using collections.namedtuple, also available in Python 3.
This was what I was looking for:
>>> d = {'a':1, 'b':2}
>>> for key,val in d.items():
exec(key + '=val')
You already have a perfectly good dictionary. Just use that. If you know what the keys are going to be, and you're absolutely sure this is a reasonable idea, you can do something like
a, b = d['a'], d['b']
but most of the time, you should just use the dictionary. (If using the dictionary is awkward, you are probably not organizing your data well; ask for help reorganizing it.)
you can use operator.itemgetter
>>> from operator import itemgetter
>>> d = {'a':1, 'b':2}
>>> a, b = itemgetter('a', 'b')(d)
>>> a
1
>>> b
2
Consider the "Bunch" solution in Python: load variables in a dict into namespace. Your variables end up as part of a new object, not locals, but you can treat them as variables instead of dict entries.
class Bunch(object):
def __init__(self, adict):
self.__dict__.update(adict)
d = {'a':1, 'b':2}
vars = Bunch(d)
print vars.a, vars.b
Python has great support for list unpacking, but not dict or object unpacking. The most unsurprising and Pythonic approach seems to be accessing each item by hand to build an intermediate tuple as described in this answer:
a, b = d['a'], d['b']
However, if you have a lot of properties, or variable names are long, it can get nasty to do:
great, wow, awesome = dictionary['great'], dictionary['wow'], dictionary['awesome']
For context, the JavaScript equivalent of the above (destructuring) is:
const {great, wow, awesome} = dictionary;
Here's an option that is a bit more dynamic:
>>> dictionary = dict(great=0, wow=1, awesome=2)
>>> great, wow, awesome = (dictionary[k] for k in ("great", "wow", "awesome"))
>>> great
0
>>> awesome
2
This is still verbose; you could write a function to abstract things a bit, but unfortunately you still have to type everything twice:
>>> def unpack(dct, *keys):
... return (dct[k] for k in keys)
...
>>> dictionary = dict(great=0, wow=1, awesome=2)
>>> great, wow, awesome = unpack(dictionary, "great", "wow", "awesome")
You can generalize this to work on objects too:
>>> def unpack(x, *keys):
... if isinstance(x, dict):
... return (x[k] for k in keys)
... return (getattr(x, k) for k in keys)
...
>>> from collections import namedtuple
>>> Foo = namedtuple("Foo", "a b c d e")
>>> foo = Foo(a=0, b=1, c=2, d=3, e=4)
>>> c, b, d, a = unpack(foo, "c", "b", "d", "a")
>>> d
3
After all is said and done, unpacking by hand on multiple lines is probably best for real production code that you need to be safe and comprehensible:
>>> great = dictionary["great"]
>>> wow = dictionary["wow"]
>>> awesome = dictionary["awesome"]
Use pandas:
import pandas as pd
var=pd.Series({'a':1, 'b':2})
#update both keys and variables
var.a=3
print(var.a,var['a'])
In Objective-C, you can use the NSDictionaryOfVariableBindings macro to create a dictionary like this
NSString *foo = #"bar"
NSString *flip = #"rar"
NSDictionary *d = NSDictionaryOfVariableBindings(foo, flip)
// d -> { 'foo' => 'bar', 'flip' => 'rar' }
Is there something similar in python? I often find myself writing code like this
d = {'foo': foo, 'flip': flip}
# or
d = dict(foo=foo, flip=flip)
Is there a shortcut to do something like this?
d = dict(foo, flip) # -> {'foo': 'bar', 'flip': 'rar'}
No, this shortcut in python does not exist.
But perhaps this is what you need:
>>> def test():
... x = 42
... y = 43
... return locals()
>>> test()
{'y': 43, 'x': 42}
Also, python provides globals() and vars() build-in functions for such things.
See the doc.
have you tried vars()
vars([object])
Return the __dict__ attribute for a module, class, instance, or any other object with a __dict__ attribute.
Objects such as modules and instances have an updateable __dict__
attribute; however, other objects may have write restrictions on their
__dict__ attributes (for example, new-style classes use a dictproxy to prevent direct dictionary updates).
so
variables = vars()
dictionary_of_bindings = {x:variables[x] for x in ("foo", "flip")}
Python doesn't quite have a way to do this, though it does have the functions locals and globals which can give you access to the entire local or global namespace. But if you want to pick out selected variables, I consider it better to use inspect. Here's a function that should do that for you:
def compact(*names):
caller = inspect.stack()[1][0] # caller of compact()
vars = {}
for n in names:
if n in caller.f_locals:
vars[n] = caller.f_locals[n]
elif n in caller.f_globals:
vars[n] = caller.f_globals[n]
return vars
Make sure to check that it works in whatever Python environment you're using. Usage would be like so:
a = 1
b = 2
def func():
c = 3
d = 4
compact('b', 'd') # returns {'b': 2, 'd': 4}
I don't think there's any way to get away without the quotes around the variable names, though.