I'm trying to better understand a way to implement a conditional variable into a python requests' http request.
I'm doing the following:
def make_post(parameter1_value, parameter2='None'):
payload = {
"parameter1": parameter1_value,
"parameter2": "None"
}
r = requests.post('https://myrequesturl.com/location/', params=payload)
I'm trying to find the best way to NOT include the "parameter2": "None" value in the params unless the value is not equal to None.
I realize I could have several conditional statements to select a proper format of request depending on the parameters, but then it would become sticky to scale for each additional parameterN needed in the function.
I'm wondering if there is a way to include a conditional type of variable in the payload that would have the effect of including that parameter only if it isn't equal to the default value set; in this case 'None'.
So if the the value of parameter2 = None:
payload = {
"parameter1": parameter1_value
}
But if the value of parameter2 = anything other than None
payload = {
"parameter1": parameter1_value,
"parameter2": "Non_default_value"
}
I'm trying to avoid the following type of approach:
if some_parameter != 'None':
payload = {
"one": "arrangement"
}
if some_some_other_parameter != 'None':
payload = {
"one": "arrangement"
}
It seems a bit impractical in an example of only two parameters, but if I were to have a function with many parameters it would seem that a one line include/exclude type expression would greatly reduce the amount of overall code required. It's been my experience when I can't figure out how to get python to do something clever it's only because I don't know how, and not that python can't.
Something like this?
def foo(v1, v2=None):
params = {k:v for k,v in locals().items() if v!=None}
print params
foo('hello')
foo('hello', 'world')
Output:
{'v1': 'hello'}
{'v1': 'hello', 'v2': 'world'}
Or
Something like this?
def foo(a={}, url=''):
params = {k:v for k,v in a.items() if v!=None}
print params
foo({'k1':'v1','k2':2,'k3':None, 'k4':'v4'})
foo()
Output:
{'k2': 2, 'k1': 'v1', 'k4': 'v4'}
{}
I think something like this would work for you, especially if the default values are specific to the key:
def optional_include_mut(payload, key, value, default=None):
"""
Mutate the given payload dict by adding the given key/value pair if the value is not equal to default.
:param payload: Dict to mutate
:param key: Key to insert into dict
:param value: Value to insert into dict
:param default: Default value to control insertion
:return: A mutated version of the payload dict
"""
if value != default:
payload[key] = value
return payload
>>> payload = dict(good=1)
>>> payload = optional_include_mut(payload, 'foo', 'bar', default='bar')
{'good': 1}
>>> payload = optional_include_mut(payload, 'foo', 'bar', default='not bar')
{'good': 1, 'foo': 'bar'}
You could use a dictionary comprehension to filter the values:
>>> payload = dict(a='value1',b='value2',c='None',d='None',e='value3')
>>> payload
{'a': 'value1', 'b': 'value2', 'c': 'None', 'd': 'None', 'e': 'value3'}
>>> {k:v for k,v in payload.items() if v != 'None'}
{'a': 'value1', 'b': 'value2', 'e': 'value3'}
how about something like this
>>> def fun(*param):
return {"parameter{}".format(k): v for k,v in enumerate(param,1) if v not in (None,"None")}
>>> fun("hello","None","world",None,42)
{'parameter1': 'hello', 'parameter5': 42, 'parameter3': 'world'}
>>>
(*param is the way to said you want a variable numbers of arguments)
this way you can pass as many parameter as you want, and filter those with invalid values
with python 3 syntax you can also do it as
def fun(*param, invalid=(None,"None")):
return {"parameter{}".format(k): v for k,v in enumerate(param,1) if v not in invalid}
for python 2 to accomplished the same would be
def fun(*param, **karg):
invalid = karg.get("invalid", (None,"None") )
return {"parameter{}".format(k): v for k,v in enumerate(param,1) if v not in invalid}
another example
>>> fun("hello","None","world",None,42,32, invalid=("None",None,32))
{'parameter1': 'hello', 'parameter5': 42, 'parameter3': 'world'}
>>>
Related
def foo():
dict_1 = dict()
dict_2 = dict()
return dict_1, dict_2
print(foo())
result: ({}, {})
But I need {}, {}
How to do it?
I am trying to return data from function but getting:
See:
[{
'root': {
'id': '17958765',
}
}, ({
'lots': [{
'purchaseNumber': '0873500000818004164'
}
]
}, {
'PurchaseObjects': [{
{
'OKPD2_code': '123',
'OKPD2_name': 'ffff'
}
]
})]
Those are the same thing, only ({}, {}) is printed in a non-ambiguous way.
The function is returning a tuple (more closely 2-tuple), not a set as your title says.
foo() will give you a 2-tuple of two dictionaries. Fetch the return value, and index or unpack the tuple to get individual access to your two dictionaries.
def foo():
dict_1 = dict()
dict_2 = dict()
return dict_1, dict_2
# Do either one of the following (indexing or unpacking)
# Indexing a tuple
return_value = foo()
dict_1 = return_value[0]
dict_2 = return_value[1]
# Unpacking a tuple
dict_1, dict_2 = foo()
In the example you gave, unpacking is apparently the better way to go, but in some cases you might want to keep the returned tuple and access its elements later with indexing.
I'm using Python3 and I tried all way of this question but no one solution works. If I do this way list(map(str.strip, my_list)) I lost all my keys because list() return just values accessible just with indice.
So I decided to trim manually with .strip() all my data but it will not work for NoneType data. I don't want to do 30 conditions...
if str:
str.strip(' ')
So do you have a solution to trim all str value in my associative array ? My array can content None, Int and String.
I'll assume that when you say "associative array" you actually mean a Python dict.
>>> d = { 'a': 'foo\n', 'b': 3, 'c': None }
>>> cleaned = { k: v.strip() if isinstance(v, str) else v for k,v in d.items() }
>>> cleaned
{'b': 3, 'a': 'foo', 'c': None}
Suppose I have a multi-level dictionary like this
mydict = {
'first': {
'second': {
'third': {
'fourth': 'the end'
}
}
}
}
I'd like to access it like this
test = get_entry(mydict, 'first.second.third.fourth')
What I have so far is
def get_entry(dict, keyspec):
keys = keyspec.split('.')
result = dict[keys[0]]
for key in keys[1:]:
result = dict[key]
return result
Are there more efficient ways to do it? According to %timeit the runtime of the function is 1.26us, while accessing the dictionary the standard way like this
foo = mydict['first']['second']['third']['fourth']
takes 541ns. I'm looking for ways to trim it to 800ns range if possible.
Thanks
I got a 20% performance boost by tightening up the code a bit but a whopping 400% increase by using a cache for split strings. That only makes a difference if you use the same spec multiple times. Here are sample implementations and a profile script to test.
test.py
mydict = {
'first': {
'second': {
'third': {
'fourth': 'the end'
}
}
}
}
# original
def get_entry(dict, keyspec):
keys = keyspec.split('.')
result = dict[keys[0]]
for key in keys[1:]:
result = result[key]
return result
# tighten up code
def get_entry_2(mydict, keyspec):
for key in keyspec.split('.'):
mydict = mydict[key]
return mydict
# use a cache
cache = {}
def get_entry_3(mydict, keyspec):
global cache
try:
spec = cache[keyspec]
except KeyError:
spec = tuple(keyspec.split('.'))
cache[keyspec] = spec
for key in spec:
mydict = mydict[key]
return mydict
if __name__ == "__main__":
test = get_entry(mydict, 'first.second.third.fourth')
print(test)
profile.py
from timeit import timeit
print("original get_entry")
print(timeit("get_entry(mydict, 'first.second.third.fourth')",
setup="from test import get_entry, mydict"))
print("get_entry_2 with tighter code")
print(timeit("get_entry_2(mydict, 'first.second.third.fourth')",
setup="from test import get_entry_2, mydict"))
print("get_entry_3 with cache of split spec")
print(timeit("get_entry_3(mydict, 'first.second.third.fourth')",
setup="from test import get_entry_3, mydict"))
print("just splitting a spec")
print(timeit("x.split('.')", setup="x='first.second.third.fourth'"))
The timing on my machine is
original get_entry
4.148535753000033
get_entry_2 with tighter code
3.2986323120003362
get_entry_3 with cache of split spec
1.3073233439990872
just splitting a spec
1.0949148639992927
Notice that splitting the spec is a comparatively expensive operation for this function. That's why caching helps.
There's really only one solution. Rebuild your dictionary. But do it just once.
def recursive_flatten(mydict):
d = {}
for k, v in mydict.items():
if isinstance(v, dict):
for k2, v2 in recursive_flatten(v).items():
d[k + '.' + k2] = v2
else:
d[k] = v
return d
In [786]: new_dict = recursive_flatten(mydict); new_dict
Out[786]: {'first.second.third.fourth': 'the end'}
(Some more tests)
In [788]: recursive_flatten({'x' : {'y' : 1, 'z' : 2}, 'y' : {'a' : 5}, 'z' : 2})
Out[788]: {'x.y': 1, 'x.z': 2, 'y.a': 5, 'z': 2}
In [789]: recursive_flatten({'x' : 1, 'y' : {'x' : 234}})
Out[789]: {'x': 1, 'y.x': 234}
Every access becomes constant time from here on.
Now, just access your value using new_dict['first.second.third.fourth']. Should work for any arbitrarily nested dictionary that does not contain a self-reference.
Note that every solution has its fair share of tradeoffs, this is no exception. Unless you're firing millions of queries at your data such that preprocessing is an acceptable overhead, then this is it. With the other solutions, you are only sidestepping the problem instead of addressing it - which is dealing with the dictionary's structure. OTOH, if you're going to do this once on many such similar data structures, it make no sense to preprocess just for a single query, in which case you may prefer one of the other solutions.
I updated the answer from How to use a dot "." to access members of dictionary? to use an initial conversion which will then work for nested dictionaries:
You can use the following class to allow dot-indexing of dictionaries:
class dotdict(dict):
"""dot.notation access to dictionary attributes"""
__getattr__ = dict.get
__setattr__ = dict.__setitem__
__delattr__ = dict.__delitem__
However, this only supports nesting if all nested dictionaries are also of type dotdict. That's where the following helper function comes in:
def dct_to_dotdct(d):
if isinstance(d, dict):
d = dotdict({k: dct_to_dotdct(v) for k, v in d.items()})
return d
This function has to be run once on your nested dictionary, and the result can then be indexed using dot-indexing.
Here are some examples:
In [13]: mydict
Out[13]: {'first': {'second': {'third': {'fourth': 'the end'}}}}
In [14]: mydict = dct_to_dotdct(mydict)
In [15]: mydict.first.second
Out[15]: {'third': {'fourth': 'the end'}}
In [16]: mydict.first.second.third.fourth
Out[16]: 'the end'
A note about performance: this answer is slow compared to standard dictionary access, I just wanted to present an option that actually used "dot access" to a dictionary.
Here is a solution similar to chrisz's, but you do not have to anything to your dict a-prior. :
class dictDotter(dict):
def __getattr__(self,key):
val = self[key]
return val if type(val) != dict else dictDotter(val)
and just x=dictDotter(originalDict) will let you have arbitrary dot getting (`x.first.second...). I'll note this is twice as slow as chrisz solution, and his is 9 times as slow as yours (on my machine, approximately).
So, if you insist on making this work #tdelaney seems to have provided the only real performance improvement.
Another option that does better than what you have (in terms of run time):
class dictObjecter:
def __init__(self,adict):
for k,v in adict.items():
self.__dict__[k] = v
if type(v) == dict: self.__dict__[k] = dictObjecter(v)
which will make an object out of your dict, so dot notation is usual. This will improve run time to 3 times what you have, so not bad, but at the cost of going over your dict, and replacing it with something else.
Here is the total testing code:
from timeit import timeit
class dictObjecter:
def __init__(self,adict):
for k,v in adict.items():
self.__dict__[k] = v
if type(v) == dict: self.__dict__[k] = dictObjecter(v)
class dictDotter(dict):
def __getattr__(self,key):
val = self[key]
return val if type(val) != dict else dictDotter(val)
def get_entry(dict, keyspec):
keys = keyspec.split('.')
result = dict[keys[0]]
for key in keys[1:]:
result = result[key]
return result
class dotdict(dict):
"""dot.notation access to dictionary attributes"""
__getattr__ = dict.get
__setattr__ = dict.__setitem__
__delattr__ = dict.__delitem__
def dct_to_dotdct(d):
if isinstance(d, dict):
d = dotdict({k: dct_to_dotdct(v) for k, v in d.items()})
return d
x = {'a':{'b':{'c':{'d':1}}}}
y = dictDotter(x)
z = dct_to_dotdct(x)
w = dictObjecter(x)
print('{:15} : {}'.format('dict dotter',timeit('y.a.b.c.d',globals=locals(),number=1000)))
print('{:15} : {}'.format('dot dict',timeit('z.a.b.c.d',globals=locals(),number=1000)))
print('{:15} : {}'.format('dict objecter',timeit('w.a.b.c.d',globals=locals(),number=1000)))
print('{:15} : {}'.format('original',timeit("get_entry(x,'a.b.c.d')",globals=locals(),number=1000)))
print('{:15} : {:.20f}'.format('best ref',timeit("x['a']['b']['c']['d']",globals=locals(),number=1000)))
I provided the last regular lookup as a best reference.The results on a Windows Ubuntu subsystem:
dict dotter : 0.0035500000003594323
dot dict : 0.0017939999997906853
dict objecter : 0.00021699999979318818
original : 0.0006629999998040148
best ref : 0.00007999999979801942
so the is objectified dict is 3 times as slow as a regular dictionary lookup - so if speed is important, why would you want this?
I had the same need, so I created the Prodict.
For your case, you can do it in one line:
mydict = {
'first': {
'second': {
'third': {
'fourth': 'the end'
}
}
}
}
dotdict = Prodict.from_dict(mydict)
print(dotdict.first.second.third.fourth) # "the end"
After that, use dotdict just like a dict, because it is a subclass of dict:
dotdict.first == dotdict['first'] # True
You can also add more keys dynamically with dot notation:
dotdict.new_key = 'hooray'
print(dotdict.new_key) # "hooray"
It works even if the new keys are nested dictionaries:
dotdict.it = {'just': 'works'}
print(dotdict.it.just) # "works"
Lastly, if you define your keys beforehand, you get auto completion and auto type conversion:
class User(Prodict):
user_id: int
name: str
user = User(user_id="1", "name":"Ramazan")
type(user.user_id) # <class 'int'>
# IDE will be able to auto complete 'user_id' and 'name' properties
UPDATE:
This is the test result for the same code written by #kabanus:
x = {'a': {'b': {'c': {'d': 1}}}}
y = dictDotter(x)
z = dct_to_dotdct(x)
w = dictObjecter(x)
p = Prodict.from_dict(x)
print('{:15} : {}'.format('dict dotter', timeit('y.a.b.c.d', globals=locals(), number=10000)))
print('{:15} : {}'.format('prodict', timeit('p.a.b.c.d', globals=locals(), number=10000)))
print('{:15} : {}'.format('dot dict', timeit('z.a.b.c.d', globals=locals(), number=10000)))
print('{:15} : {}'.format('dict objecter', timeit('w.a.b.c.d', globals=locals(), number=10000)))
print('{:15} : {}'.format('original', timeit("get_entry(x,'a.b.c.d')", globals=locals(), number=10000)))
print('{:15} : {:.20f}'.format('prodict getitem', timeit("p['a']['b']['c']['d']", globals=locals(), number=10000)))
print('{:15} : {:.20f}'.format('best ref', timeit("x['a']['b']['c']['d']", globals=locals(), number=10000)))
And results:
dict dotter : 0.04535976458466595
prodict : 0.02860781018446784
dot dict : 0.019078164088831673
dict objecter : 0.0017378700050722368
original : 0.006594238310349346
prodict getitem : 0.00510931794975705289
best ref : 0.00121740293554022105
As you can see, its performance is between "dict dotter" and "dot dict".
Any performance enhancement suggestion will be appreciated.
The code should be less iterative and more dynamic!!
data
mydict = {
'first': {
'second': {
'third': {
'fourth': 'the end'
}
}
}
}
Function
def get_entry(dict, keyspec):
for keys in keyspec.split('.'):
dict = dict[keys]
return dict
call the function
res = get_entry(mydict, 'first.second.third.fourth')
this will take less time to execute even it's a dynamic code execution!!
You can use reduce (functools.reduce in python3):
import operator
def get_entry(dct, keyspec):
return reduce(operator.getitem, keyspec.split('.'), dct)
It is more nicely looking but with a little less perfomance.
Your version timeit:
>>> timeit("get_entry_original(mydict, 'first.second.third.fourth')",
"from __main__ import get_entry_original, mydict", number=1000000)
0.5646841526031494
with reduce:
>>> timeit("get_entry(mydict, 'first.second.third.fourth')",
"from __main__ import get_entry, mydict")
0.6140949726104736
As tdelaney notice - split consume almost as much cpu power as getting key in dict:
def split_keys(keyspec):
keys = keyspec.split('.')
timeit("split_keys('first.second.third.fourth')",
"from __main__ import split_keys")
0.28857898712158203
Just move string splitting away from get_entry function:
def get_entry(dct, keyspec_list):
return reduce(operator.getitem, keyspec_list, dct)
timeit("get_entry(mydict, ['first', 'second', 'third', 'fourth'])",
"from __main__ import get_entry, mydict")
0.37825703620910645
Is a dictionary the right type for data where I want to look up entries based on an index, e.g.
dictlist = {}
dictlist['itemid' + '1'] = {'name':'AAA', 'class':'Class1', 'nonstandard':'whatever'}
dictlist['itemid' + '2'] = {'name':'BBB', 'class':'Class2', 'maynotbehere':'optional'}
dictlist['itemid' + '3'] = {'name':'CCC', 'class':'Class3', 'regular':'or not'}
I can now address a specific item, e.g.
finditem='itemid2'
dictitem = {}
try:
dictitem[finditem] = dictlist[finditem]
print dictitem
except KeyError:
print "Nothing there"
Is that the right way to create such a lookup table in python?
If I now wanted to print the data, but only the Item ID, and an associated dictionary with only name and class "properties", how can I do that?
I am looking for something that will create a new dictionary by copying the desired properties only, or else present a limited view of the existing dictionary, as if the unspecified properties were not there. So for example
view(dictlist, 'name', 'class')
will return a dictionary that displays a restricted view of the list, showing only the name and class keys. I have tried
view = {}
for item in dictlist:
view[item] = {dictlist[item]['name'], dictlist[item]['class']}
print view
Which returns
{'itemid1': set(['AAA', 'Class1']), 'itemid3': set(['Class3', 'CCC']), 'itemid2': set(['Class2', 'BBB'])}
Instead of
{'itemid1': {'name':'AAA', 'class':'Class1'}, 'itemid3': {'name':'CCC', 'class':'Class3'}, 'itemid2': {'name':'BBB', 'class':'Class2'} }
Note that {'foo', 'bar'} is a set literal, not a dictionary literal, as it does not have the key: value syntax required for a dictionary:
>>> type({'foo', 'bar'})
<class 'set'>
>>> type({'foo': 'bar'})
<class 'dict'>
You need to be more careful with your syntax generally; I have no idea what the random closing square brackets ] are doing in the output you claim you want, and it's missing a closing brace }.
You could extend your current code to do keys and values as follows:
for item in dictlist:
view[item] = {'name': dictlist[item]['name'],
'class': dictlist[item]['class']}
but a more generic function would look like:
def view(dictlist, *keys):
output = {}
for item in dictlist:
output[item] = {}
for key in keys:
output[item][key] = dictlist[item].get(key)
return output
note the use of dict.get to handle missing keys gracefully:
>>> d = {'foo': 'bar'}
>>> d.get('foo')
'bar' # returns the value if key present, or
>>> d.get('baz')
>>> # returns None by default
or, using a "dictionary comprehension":
def view(dictlist, *keys):
return {k1: {k2: v2 for k2, v2 in v1.items() if k2 in keys}
for k1, v1 in dictlist.items()}
(This will exclude missing keys from the output, whereas the previous code will include them with None value - which is preferable will depend on your use case.)
Note the use of *keys to take an arbitrary number of positional arguments:
>>> def test(d, *keys):
print(keys)
>>> test({}, "foo", "bar", "baz")
('foo', 'bar', 'baz')
This question already has answers here:
Python unittest's assertDictContainsSubset recommended alternative [duplicate]
(4 answers)
Closed 1 year ago.
I know assertDictContainsSubset can do this in python 2.7, but for some reason it's deprecated in python 3.2. So is there any way to assert a dict contains another one without assertDictContainsSubset?
This seems not good:
for item in dic2:
self.assertIn(item, dic)
any other good way? Thanks
Although I'm using pytest, I found the following idea in a comment. It worked really great for me, so I thought it could be useful here.
Python 3:
assert dict1.items() <= dict2.items()
Python 2:
assert dict1.viewitems() <= dict2.viewitems()
It works with non-hashable items, but you can't know exactly which item eventually fails.
>>> d1 = dict(a=1, b=2, c=3, d=4)
>>> d2 = dict(a=1, b=2)
>>> set(d2.items()).issubset( set(d1.items()) )
True
And the other way around:
>>> set(d1.items()).issubset( set(d2.items()) )
False
Limitation: the dictionary values have to be hashable.
The big problem with the accepted answer is that it does not work if you have non hashable values in your objects values. The second thing is that you get no useful output - the test passes or fails but doesn't tell you which field within the object is different.
As such it is easier to simply create a subset dictionary then test that. This way you can use the TestCase.assertDictEquals() method which will give you very useful formatted output in your test runner showing the diff between the actual and the expected.
I think the most pleasing and pythonic way to do this is with a simple dictionary comprehension as such:
from unittest import TestCase
actual = {}
expected = {}
subset = {k:v for k, v in actual.items() if k in expected}
TestCase().assertDictEqual(subset, expected)
NOTE obviously if you are running your test in a method that belongs to a child class that inherits from TestCase (as you almost certainly should be) then it is just self.assertDictEqual(subset, expected)
John1024's solution worked for me. However, in case of a failure it only tells you False instead of showing you which keys are not matching. So, I tried to avoid the deprecated assert method by using other assertion methods that will output helpful failure messages:
expected = {}
response_keys = set(response.data.keys())
for key in input_dict.keys():
self.assertIn(key, response_keys)
expected[key] = response.data[key]
self.assertDictEqual(input_dict, expected)
You can use assertGreaterEqual or assertLessEqual.
users = {'id': 28027, 'email': 'chungs.lama#gmail.com', 'created_at': '2005-02-13'}
data = {"email": "chungs.lama#gmail.com"}
self.assertGreaterEqual(user.items(), data.items())
self.assertLessEqual(data.items(), user.items()) # Reversed alternative
Be sure to specify .items() or it won't work.
In Python 3 and Python 2.7, you can create a set-like "item view" of a dict without copying any data. This allows you can use comparison operators to test for a subset relationship.
In Python 3, this looks like:
# Test if d1 is a sub-dict of d2
d1.items() <= d2.items()
# Get items in d1 not found in d2
difference = d1.items() - d2.items()
In Python 2.7 you can use the viewitems() method in place of items() to achieve the same result.
In Python 2.6 and below, your best bet is to iterate over the keys in the first dict and check for inclusion in the second.
# Test if d1 is a subset of d2
all(k in d2 and d2[k] == d1[k] for k in d1)
This answers a little broader question than you're asking but I use this in my test harnesses to see if the container dictionary contains something that looks like the contained dictionary. This checks keys and values. Additionally you can use the keyword 'ANYTHING' to indicate that you don't care how it matches.
def contains(container, contained):
'''ensure that `contained` is present somewhere in `container`
EXAMPLES:
contains(
{'a': 3, 'b': 4},
{'a': 3}
) # True
contains(
{'a': [3, 4, 5]},
{'a': 3},
) # True
contains(
{'a': 4, 'b': {'a':3}},
{'a': 3}
) # True
contains(
{'a': 4, 'b': {'a':3, 'c': 5}},
{'a': 3, 'c': 5}
) # True
# if an `contained` has a list, then every item from that list must be present
# in the corresponding `container` list
contains(
{'a': [{'b':1}, {'b':2}, {'b':3}], 'c':4},
{'a': [{'b':1},{'b':2}], 'c':4},
) # True
# You can also use the string literal 'ANYTHING' to match anything
contains(
{'a': [{'b':3}]},
{'a': 'ANYTHING'},
) # True
# You can use 'ANYTHING' as a dict key and it indicates to match the corresponding value anywhere
# below the current point
contains(
{'a': [ {'x':1,'b1':{'b2':{'c':'SOMETHING'}}}]},
{'a': {'ANYTHING': 'SOMETHING', 'x':1}},
) # True
contains(
{'a': [ {'x':1, 'b':'SOMETHING'}]},
{'a': {'ANYTHING': 'SOMETHING', 'x':1}},
) # True
contains(
{'a': [ {'x':1,'b1':{'b2':{'c':'SOMETHING'}}}]},
{'a': {'ANYTHING': 'SOMETHING', 'x':1}},
) # True
'''
ANYTHING = 'ANYTHING'
if contained == ANYTHING:
return True
if container == contained:
return True
if isinstance(container, list):
if not isinstance(contained, list):
contained = [contained]
true_count = 0
for contained_item in contained:
for item in container:
if contains(item, contained_item):
true_count += 1
break
if true_count == len(contained):
return True
if isinstance(contained, dict) and isinstance(container, dict):
contained_keys = set(contained.keys())
if ANYTHING in contained_keys:
contained_keys.remove(ANYTHING)
if not contains(container, contained[ANYTHING]):
return False
container_keys = set(container.keys())
if len(contained_keys - container_keys) == 0:
# then all the contained keys are in this container ~ recursive check
if all(
contains(container[key], contained[key])
for key in contained_keys
):
return True
# well, we're here, so I guess we didn't find a match yet
if isinstance(container, dict):
for value in container.values():
if contains(value, contained):
return True
return False
Here is a comparison that works even if you have lists in the dictionaries:
superset = {'a': 1, 'b': 2}
subset = {'a': 1}
common = { key: superset[key] for key in set(superset.keys()).intersection(set(subset.keys())) }
self.assertEquals(common, subset)