Использование True / False в качестве ключей-как/почему это работает?


Мне удобно использовать этот простой синтаксис для инициализации a dictionary

d = {'a':'Apple','b':'Bat'};

Сегодня, читая страницу, Я столкнулся с этим странным фрагментом кода

{True:0, False:1}[True];

Мне было интересно, почему/как это может работать? True и False - зарезервированные ключевые слова., и так, этот безумный синтаксис должен быть бессмысленным (для компилятора), но он есть нет.

>>> d = {True:0, False:1};
>>> d
{False: 1, True: 0}

И это становится еще безумнее

>>> d = dict(True = 0, False = 1);
SyntaxError: assignment to keyword
>>> d = dict(_True = 0, _False = 1);
>>> d
{'_False': 1, '_True': 0}

В конструкторе dict() ключевое слово True не допускается! Но...


обновление
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
3 4

3 ответа:

Хотя они и являются ключевыми словами (в Python 3), True и False по-прежнему являются именами объектов (они, соответственно bool(1) и bool(0)).

Таким образом, вы можете использовать их везде, где значение имеет смысл. Поскольку они хешируются, это включает в себя использование их в качестве ключей словаря. Вы можете сделать:
d = {}
d[True] = "True"
d[False] = "False"

Вы можете получить тот же словарь непосредственно с фигурными скобками (d = {True: "True", False: "False"}), но не используя конструктор dict с аргументами ключевых слов. Ключевая версия конструктора строит только дикты с ключами, которые являются строками, и эти строки должны быть легальными идентификаторами Python. True и False не являются строками и (поскольку они являются ключевыми словами) не могут использоваться в качестве идентификаторов.

Вы, конечно, можете использовать конструктор последовательности кортежей ключей/значений, если есть какая-то причина, по которой вам нужно вызывать dict, а не использовать скобки:

d = dict([(True, "True"), (False, "False")])
Я бы отметил, что фрагмент кода, который вы показываете, немного глуповат. Тип bool в Python является подклассом int, поэтому вы можете выполнять математические операции над True или False, Если хотите. Код индексации словаря эквивалентен 1-True, который будет 0.

Почему это должно быть бессмысленно? True и False - это значения, а не ключевые слова. Вот почему вы можете сравнить с ними другие ценности.

Вы также не можете использовать целые числа в конструкторе dict. Это ограничение аргументов ключевых слов, а не словарей.

True и False - это не ключевые слова , а реальные объекты. Вы можете проверить это в интерпретаторе Python (здесь используется 2.7, но то же самое относится и к 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>
Таким образом, они могут использоваться в качестве ключей в dict или подобной структуре.

Фактически, до Python 3, Вы могли использовать True и False в качестве имен параметров для dict():

>>> d = dict(True="true", False="false")
>>> d
{'False': 'false', 'True': 'true'}

Однако, чтобы избежать путаницы, интерпретатор Python 3 запрещает вам это делать, так как теперь он по существу обрабатывает их как ключевые слова -- но на самом деле они все еще объекты. (Я думаю, можно сказать, что они оба, в некотором роде.)