А вы знали про hash(-1)?

(Речь идет о реализации CPython)

Встроенная функция hash возвращает целое число – хэш-сумму, которое используется при сравнении ключей словаря во время поиска, например. Для пользовательских классов hash вызывает магический метод класса  __hash__ , а для примитивных типов уже есть встроенная реализация на Си. 

Примечательно, что для чисел hash обычно возвращает само же значение числа-аргумента, кроме нескольких случаев. Запустим этот код:

def print_hash(x):
    print(f'hash({x}) = {hash(x)}')
for i in range(2, -4, -1):
    print_hash(i)

Вывод:

hash(2) = 2
hash(1) = 1
hash(0) = 0
hash(-1) = -2  <-- что?
hash(-2) = -2
hash(-3) = -3

Оказывается hash не возвращает -1, а конвертирует его явно в -2. Я изучил исходный код на Си и нашел это место. «Легенда гласит», что в CPython число -1 зарезервировано внутренне для индикации ошибок при выполнении этой функции.

Еще интереснее для рациональных чисел. От hash от NAN – ноль. Плюс еще пасхалка: hash от бесконечности возращает первые несколько цифр числа π. 

print_hash(-1.0)  # -2
print_hash(float('nan'))  # 0
print_hash(float('+inf'))  # 314159
print_hash(float('-inf'))  # -314159

🧙 Специально для канала @pyway. Подписывайтесь на мой канал в Телеграм @pyway 👈 

🤭 Счастливой отладки

Python не запрещает создавать переменные и функции с именами, идентичными встроенным. Шутки ради переопределим print:

import sys

# счастилвой отладки!
def print(*values, sep=' ', end='\n', file=sys.stdout, flush=False):
    # шутка
    def joke(value):
        if type(value) is str:
            value = value[::-1]
        elif type(value) is int:
            value += 1
        return value

    # отсюда достанем исходную версию print
    import builtins
    return builtins.print(*map(joke, reversed(values)),
                          sep=sep, end=end, file=file, flush=flush)


print('Hello, world!', '2 x 2 =', 4)  # 5 = 2 x 2 !dlrow ,olleH

Мораль такова. Во-первых, нужно быть внимательным, когда даешь имена своим переменным и функциям, чтобы случайно не перекрыть встроенные имена, что может нарушить работу программы. Хорошая IDE вас, конечно, предупредит о перекрытии имен. Во-вторых, это иногда применимо для отладки или тестирования. Но помните, что программист, читающий ваш код, ожидает от встроенных функций их обычного нормального поведения, а не того, которое вы придумали. Лучше создать обертку с явно другим именем.

🤩 Специально для канала @pyway. Подписывайтесь на мой канал в Телеграм @pyway!👈

Шедевры Нижегородского ритейла

И. Импортозамещение. Кокосы, лаймы и авокадо с солнечных плантаций Поветлужья.

Снято в Пятерочке в городе Воскресенское Нижегородской области. Кстати, из одного из таких кокосов я делал на Марь-Яре бокал. В этом году я повторю подвиг, правда учту на этот раз строение плода: дно не может быть там, где у кокоса три точки.

k7q-eYPa3kw

Нижегородские самураи рекомендуют.

В магазине Familia на Автозаводе продают тонны всякого хлама. Неудивительно, что нож «Харакири» обнаружился именно там. Надеюсь, им будут пользоваться не по древней японской традиции, а просто резать продукты.

wd9zE1xS6Ds