Недавно мне довелось послушать доклад о хороших и плохих практиках программирования на языке Си. В нем, в частности, была затронута тема расшифровки забавно выглядящего программного кода (смайликов в Си). После чего последовал спор о целесообразности использования такого запутанного кода для проверки навыков кандидата на должность программиста при собеседованиях. Спор не привел к единому мнению.
Рассмотрим возможный вопрос по смайликам при собеседовании на должность, подразумевающую знание языка программирования Python.

Имеются два выражения:
Какое из этих двух выражений чаще будет приводить к возникновению ошибки и почему?
В Python символ подчеркивания не является ключевым словом, поэтому, в общем случае, его можно использовать для присвоения некоторых значений переменных.
Задача сводится к рассмотрению случаев появления ошибок при сложении и при «побитовом или» (для краткости - просто «или») одной переменной. Т.е. к поиску встроенных типов (классов) Python для которых реализована одна операция и к поиску встроенных типов где реализована другая операция.
В консоли Python легко проверить, что существуют такие значения подчеркивания при которых:
Магия Python заключается в том, что реализация и сложения, и «или», и других операторов находится в, так называемых, «магических методах», описанных для требуемых классов.
Для сложения это метод
Для «или» это метод
В названии каждого магического метода присутствуют символы подчеркивания, по два в начале и в конце соответствующего слова.
Встроенные классы, для которых реализованы наши методы:
Девять встроенных классов реализуют операцию сложения и четыре реализуют «или».
Дополнительно можно попытаться порассуждать про частоту использования базовых классов в реальных проектах, про небазовые классы и реализацию указанных выше методов для них. Вероятно, это будет положительно оценено при собеседовании.
Рассмотрим возможный вопрос по смайликам при собеседовании на должность, подразумевающую знание языка программирования Python.

Задача
Имеются два выражения:
_+_
_|_
Какое из этих двух выражений чаще будет приводить к возникновению ошибки и почему?
Замечания к выражениям
Следует отметить, что данные выражения плохо читаются, такие выражения не целесообразно использовать в рабочем коде, а можно использовать только в качестве головоломки.
Также нужно помнить, что смайлики в задаче написаны не питонично (не соответствуют стандарту стиля PEP 8).
Также нужно помнить, что смайлики в задаче написаны не питонично (не соответствуют стандарту стиля PEP 8).
Решение
В Python символ подчеркивания не является ключевым словом, поэтому, в общем случае, его можно использовать для присвоения некоторых значений переменных.
Задача сводится к рассмотрению случаев появления ошибок при сложении и при «побитовом или» (для краткости - просто «или») одной переменной. Т.е. к поиску встроенных типов (классов) Python для которых реализована одна операция и к поиску встроенных типов где реализована другая операция.
В консоли Python легко проверить, что существуют такие значения подчеркивания при которых:
- В вычислении каждого выражения нет ошибки
>>> _ = 10 >>> _+_ 20 >>> _ = 10 >>> _|_ 10
- В вычислении первого выражения нет ошибки
>>> _ = '10' >>> _+_ '1010' >>> _ = '10' >>> _|_ Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unsupported operand type(s) for |: 'str' and 'str'
- В вычислении второго выражения нет ошибки
>>> _ = {1, 0} >>> _+_ Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unsupported operand type(s) for +: 'set' and 'set' >>> _|_ {0, 1}
- В вычислении каждого выражения - ошибка
>>> _ = {1: 0} >>> _+_ Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unsupported operand type(s) for +: 'dict' and 'dict' >>> _|_ Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unsupported operand type(s) for |: 'dict' and 'dict'
Магия Python заключается в том, что реализация и сложения, и «или», и других операторов находится в, так называемых, «магических методах», описанных для требуемых классов.
Для сложения это метод
__add__
Для «или» это метод
__or__
В названии каждого магического метода присутствуют символы подчеркивания, по два в начале и в конце соответствующего слова.
Поиск информации о встроенных классах Python.
Можно пытаться отыскать требуемую информацию в документации к встроенным типам на официальном сайте Python: https://docs.python.org/3.7/library/stdtypes.html.
Можно в терминале Python выполнить
Я предпочитаю использовать документацию именно той версии Python, которую я использую в данный момент, обращаясь к web-интерфейсу модуля pydoc.
Для этого в командной строке вводим, например:
и открываем в браузере документацию модуля http://localhost:3344/builtins.html.
Можно в терминале Python выполнить
>>> import builtins
>>> help(builtins)
Я предпочитаю использовать документацию именно той версии Python, которую я использую в данный момент, обращаясь к web-интерфейсу модуля pydoc.
Для этого в командной строке вводим, например:
python3 -m pydoc -p 3344
и открываем в браузере документацию модуля http://localhost:3344/builtins.html.
Встроенные классы, для которых реализованы наши методы:
__add__ | __or__ |
---|---|
bool | bool |
bytearray | frozenset |
bytes | int |
complex | set |
float | |
int | |
list | |
str | |
tuple |
Девять встроенных классов реализуют операцию сложения и четыре реализуют «или».
Дополнительно можно попытаться порассуждать про частоту использования базовых классов в реальных проектах, про небазовые классы и реализацию указанных выше методов для них. Вероятно, это будет положительно оценено при собеседовании.
Ответ 1.
Второе выражение чаще будет приводить к возникновению ошибки.
Возможные дополнительные вопросы про подчеркивание на собеседовании
Какова роль подчеркивания в именовании объектов?
Ответ 2.
Символ подчеркивания может использоваться для разделения слов в разных стилях именования сущностей в Python:
Некоторые имена, ограниченные символами подчеркивания, являются зарезервированными:
- При именовании в нижнем регистре
lower_case_with_underscores
- При именовании в верхнем регистре
UPPER_CASE_WITH_UNDERSCORES
Некоторые имена, ограниченные символами подчеркивания, являются зарезервированными:
- С символом подчеркивания в начале имени не импортируется при общем импорте
from module import *
- С двумя символами подчеркивания с обеих сторон имени считается системным, не рекомендуется использовать такие имена в других целях
- С двумя символами подчеркивания в начале имени считается приватным (не публичным) для класса
Какова роль отдельного символа подчеркивания?
Ответ 3.
В интерпретаторе, если символ подчеркивания не был явно использован в качестве переменной, хранит результат последнего неошибочного действия, выведенного на экран.
Это связано с тем, что sys.stdout экранируется с помощью displayhook. Возьмем пример из официальной документации:
Кроме того единичное подчеркивание принято использовать для удобства интернализации.
$ python3
Python 3.6.8 (default, Feb 14 2019, 22:09:48)
[GCC 7.4.0] on cygwin
Type "help", "copyright", "credits" or "license" for more information.
>>> _
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name '_' is not defined
>>> 2 * 5
10
>>> _
10
>>> _ = 1
>>> _
1
>>> 2 * 5
10
>>> _
1
Это связано с тем, что sys.stdout экранируется с помощью displayhook. Возьмем пример из официальной документации:
def displayhook(value):
if value is None:
return
# Set '_' to None to avoid recursion
builtins._ = None
text = repr(value)
try:
sys.stdout.write(text)
except UnicodeEncodeError:
bytes = text.encode(sys.stdout.encoding, 'backslashreplace')
if hasattr(sys.stdout, 'buffer'):
sys.stdout.buffer.write(bytes)
else:
text = bytes.decode(sys.stdout.encoding, 'strict')
sys.stdout.write(text)
sys.stdout.write("\n")
builtins._ = value
Кроме того единичное подчеркивание принято использовать для удобства интернализации.