Читая Встроенные константы, можно увидеть, что, например, False
— это встроенная константа.
Получить его можно с помощью:
>>> print(getattr(__builtins__, "False"))
False
Но это не удается:
>>> print(__builtins__.False)
File "<stdin>", line 1
print(__builtins__.False)
^^^^^
SyntaxError: invalid syntax
Я предполагаю, что это не удается, потому что слово False
распознается интерпретатором как ключевое слово/константа, на которое оно ссылается, и поэтому поиск атрибута не происходит?
В документации говорится о getattr
:
Возвращает значение именованного атрибута объекта. имя должно быть строкой. Если строка является именем одного из атрибутов объекта, результатом будет значение этого атрибута. Например,
getattr(x, 'foobar')
эквивалентноx.foobar
.
Но для зарезервированного ключевого слова (?) это не так?
«и поэтому поиск атрибутов не выполняется». Вы даже не дошли до поиска атрибутов. False маркируется как ключевое слово до того, как парсер его проверит, поэтому __builtins__.False
— это просто недопустимый синтаксис.
@Barmar Он также включает константы; см. документацию . Он также включает встроенные исключения и типы, но они по какой-то причине не упоминаются в документации.
В выражениях атрибутов , some_obj.some_attr
some_attr
должно быть допустимым именем Python (идентификатором), а False
не является таковым именно потому, что это ключевое слово. Отсюда и синтаксическая ошибка (код даже не компилируется).
>>> import keyword
>>> keyword.iskeyword("False")
True
Сравните разницу между:
>>> import dis
>>> dis.dis("sum")
0 0 RESUME 0
1 2 LOAD_NAME 0 (sum)
4 RETURN_VALUE
>>> dis.dis("False")
0 0 RESUME 0
1 2 RETURN_CONST 0 (False)
>>> dis.dis("1337")
0 0 RESUME 0
1 2 RETURN_CONST 0 (1337)
@nocomment они являются действительными идентификаторами только в том смысле, что они были бы действительными идентификаторами, если бы не тот факт, что они являются зарезервированными словами.
@nocomment еще раз: они не являются допустимыми идентификаторами именно потому, что являются ключевыми словами. Вот почему он поднимает SyntaxError
Я имею в виду «недействителен», как в «не может использоваться в качестве обычных идентификаторов», что является определением ключевого слова, а не как в «иначе не будет действительным идентификатором».
Я предполагаю, что это не удается, потому что слово
False
распознается интерпретатором как ключевое слово [...] и поэтому поиск атрибутов не выполняется.
Да, это правильно. Вот почему вы получаете SyntaxError
вместо ошибки выполнения, например AttributeError
.
Другие встроенные константы вполне доступны, например:
>>> __builtins__.NotImplemented
NotImplemented
См. документацию по ключевым словам :
Следующие идентификаторы используются как зарезервированные слова или ключевые слова языка и не могут использоваться как обычные идентификаторы. Их нужно писать именно так, как написано здесь:
False None True
[...]
Сравните это с последним предложением документа getattr():
name не обязательно должен быть идентификатором Python (см. setattr()).
И в setattr():
Атрибут, имя которого не является идентификатором, не будет доступен с использованием точечной записи, но доступен через
getattr()
и т. д.
Это означает, что вы также можете устанавливать/получать атрибуты, которые даже отдаленно не являются синтаксически допустимыми для Python, например:
>>> class Foo: pass
...
>>> f = Foo()
>>> setattr(f, '$', 'bar')
>>> getattr(f, '$')
'bar'
>>> f.$
File "<stdin>", line 1
f.$
^
SyntaxError: invalid syntax
Спасибо, идеальное объяснение. Ответ принят!
Я думаю, что
__builtins__
предназначен только для встроенных функций, а не для переменных.