Reputation: 4204
I am comfortable using this simple syntax for initializing a dictionary
d = {'a':'Apple','b':'Bat'};
Today, while reading a page, I encountered this weird piece of code
{True:0, False:1}[True];
I was wondering why/how that could work? True
and False
are reserved keywords,
and so, that crazy syntax should be meaningless (for the compiler), but it is
not.
>>> d = {True:0, False:1};
>>> d
{False: 1, True: 0}
And this gets crazier
>>> d = dict(True = 0, False = 1);
SyntaxError: assignment to keyword
>>> d = dict(_True = 0, _False = 1);
>>> d
{'_False': 1, '_True': 0}
In dict()
constructor, True
keyword is not allowed! But...
Python 3.3.2 (v3.3.2:d047928ae3f6, May 16 2013, 00:03:43) [MSC v.1600 32 bit (Intel)] on win32
Type "copyright", "credits" or "license()" for more information.
>>> import keyword
>>> keyword.iskeyword('print');
False
>>> keyword.iskeyword('else');
True
>>> keyword.iskeyword('True');
True
>>> keyword.iskeyword('False');
True
Upvotes: 15
Views: 25923
Reputation: 104842
While they are keywords (in Python 3), True
and False
are still names of objects (they are, respectively bool(1)
and bool(0)
).
So you can use them anywhere a value makes sense. Since they're hashable, that includes using them as dictionary keys. You can do:
d = {}
d[True] = "True"
d[False] = "False"
You can get the same dictionary directly with curly brackets (d = {True: "True", False: "False"}
), but not using the dict
constructor with keyword arguments. The keyword version of the constructor only builds dicts with keys that are strings, and those strings must be legal Python identifiers. True
and False
are not strings, nor (since they're keywords) can they be used as identifiers.
You can of course use the sequence of key/value tuples constructor, if there's some reason you need to be calling dict
rather than using brackets:
d = dict([(True, "True"), (False, "False")])
I would note that the code fragment you show is a bit silly. The bool
type in Python is a subclass of int
, so you can do mathematical operations on True
or False
if you want. The dictionary indexing code is equivalent to 1-True
, which will be 0
.
Upvotes: 16
Reputation: 411252
True
and False
aren't keywords -- they're actual objects. You can verify this in the Python interpreter (using 2.7 here, but the same holds in 3.x):
Python 2.7.6 (default, Jan 29 2014, 21:22:07)
[GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.2.79)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> type(True)
<type 'bool'>
>>> True.__class__.__name__
'bool'
>>> type(False)
<type 'bool'>
>>> False.__class__.__name__
'bool'
>>> hash(True)
1
>>> hash(False)
0
>>> True.__hash__
<method-wrapper '__hash__' of bool object at 0x100134da0>
>>> False.__hash__
<method-wrapper '__hash__' of bool object at 0x100134db8>
So they can be used as keys in a dict or similar structure.
In fact, prior to Python 3, you could use True
and False
as parameter names to dict()
:
>>> d = dict(True="true", False="false")
>>> d
{'False': 'false', 'True': 'true'}
However, to avoid confusion, the Python 3 interpreter prevents you from doing that, as it essentially treats them like keywords now -- but really, they're still objects. (I guess you could say they're both, sort of.)
Upvotes: 2
Reputation: 600041
Why should it be meaningless? True
and False
are values, not keywords. That's why you can compare other values with them.
You can't use integers in the dict constructor, either. That's a limitation of keyword arguments, not of dictionaries.
Upvotes: 4