I was trying to read an example when i stumbled upon a form i couldn't quite understand:
my_values = parse_qs("red=5&blue=0&green=", keep_blank_values=True)
opacity = my_values.get("opacity", [""])[0] or 0
The code was calling a dict i made and made a parameter for when the value is missing then added "[0] or 0" part to the code which i couldn't understand how it works
So i tried to run the code asking for a key that wasn't there to run the parameter and it gave me zero as an answer to my unidentified key
when i tried to run the same code without "[0] or 0" part it gave an empty list "[""]" for the unknown key and when i removed the "or 0" part the answer changed to just this ""
So what functionality is this? so i can read more about it?
Thanks in advance
CodePudding user response:
This is an occasional pattern used to handle falsy values and also non-existent keys in a dictionary. For instance,
>>> d1 = {"opacity": ""}
>>> d2 = {"opacity": None}
>>> d3 = {}
>>> d1.get("opacity") or 0
0
>>> d2.get("opacity") or 0
0
>>> d3.get("opacity") or 0
0
All 3 of them give you the same result without throwing a key error.
CodePudding user response:
Given my_values
as you defined them, the following is its value-
{'red': ['5'], 'blue': ['0'], 'green': ['']}
>>> my_values.get("red", [""])
['5']
>>> my_values.get("red", [""])[0]
'5'
>>> my_values.get("opacity", [""])
[""]
>>> my_values.get("opacity", [""])[0]
""
So the expresion you want is probably my_values.get(color, [""])[0]
or my_values.get(color, [None])[0]
, which will return None
if the color is not found.
CodePudding user response:
the code some_dict.get("some_key", [""])[0] or 0
have 3 working parts, lets dissect them
First, lets start with the or
part, or is a boolean operator (of the same name), and can also be looked at as the following function
def or_(a,b):
if bool(a):
return a
else:
return b
(but unlike the function version it have the capability of short-circuit)
>>> 1 or 2
1
>>> 0 or 2
2
>>> "hello" or "world"
'hello'
>>> "" or "world"
'world'
>>> "hello" or 0
'hello'
>>> "" or 0
0
as for the short-circuit, it means that the second expression isn't evaluated if the first is Truth
>>> 1 or 1/0 # no error here because 1/0 isn't evaluated
1
>>> 0 or 1/0
Traceback (most recent call last):
File "<pyshell#1>", line 1, in <module>
0 or 1/0
ZeroDivisionError: division by zero
The second part is the .get in some_dict.get("some_key", [""]), that is the same as some_dict["some_key"] but without the throwing KeyError on a missing key and instead returning the second argument (if given, None otherwise), your default value, that in this case is [""]
>>> some_dict = {"a":1,"b":2,"c":3}
>>> some_dict.get("a",32)
1
>>> some_dict.get("xxx",32)
32
>>>
And finally the [0] and the end of some_dict.get("some_key", [""])[0], here there is an implicit assumption that whatever you get from the dict is something you can index, like a list, tuple, string, etc. and you want the first element of it, that is why the second argument for .get is a list with a single element, so even in the case when the key is missing, your default value is a list with a single element, so you get that at the end
>>> some_dict = {"a":[1,2,3],"b":[4,5],"c":[6]}
>>> some_dict.get("a",[""])
[1, 2, 3]
>>> some_dict.get("a",[""])[0]
1
>>> some_dict.get("xxx",[""])
['']
>>> some_dict.get("xxx",[""])[0]
''
>>>
So with all that combined, then you get either the first element of the value for that key if it is truth or 0 if not or is missing