В Python очень классной идеей является возможность переопределять взаимодействие объекта с любыми операторами, в том числе и унарные операторы.
И это можно очень интересно применить!
Долгое время меня смущало отсутствие возможности инкрементировать число на 1 с помощью синтаксиса С++. То есть вот так:
val++
Эта команда просто прибавляет единицу к значению val. В Python аналогичная операция делается так:
val += 1
Ну такой cебе ZEN😭.
Давайте напишем класс, который сможет провернуть что-то подобное. А именно, сделаем чтобы величина значения увеличивалась на 1 с помощью такой записи:
>>> c = Counter()
>>> print(c)
0
>>> +c
1
Да, вместо x++ мы сделаем +x, чтобы не конфликтовать со стандартным синтаксисом. Но и это уже не плохо!
Для взаимодействия с оператором "+" есть магический метод __add__, но для бинарного оператора. То есть когда операнда два. Для унарной версии оператора "+" есть метод __pos__, что означает positive. То есть как себя ведёт объект когда его пытаются сделать положительным. Вот его и используем:
class Counter(object):
def __init__(self, init=0):
self.val = init
def __pos__(self, *args):
self.val += 1
def __repr__(self):
return 'Count: {}'.format(self.val)
Чтобы удобно было смотреть на результат, добавил метод __repr__. Проверяем что получится.
>>> c = Counter()
>>> print(c)
Count: 0
>>> +c
Count: 1
>>> +c
Count: 2
Отлично, сделали счётчик с необычным синтаксисом! Добавим аналогичный метод для оператора "-" __neg__, что означает negate и описывает реакцию на попытку сделать число отрицательным. Теперь можем двигать значение в обе стороны:
>>> class Counter(object):
...
>>> def __neg__(self):
>>> self.val -= 1
>>> c = Counter(5)
>>> print(c)
Count: 5
>>> +c
Count: 6
>>> -c
Count: 5
Стоит учесть, что данная реализация методов изменяет сам объект а не возвращает новый изменённый, как это принято в Python. Так что весь пример не очень Pythonic-way). Но такое решение реализует необходимый нам минималистичный синтаксис.
Не буду утверждать, что пример получился полезным с точки зрения использования в реальной работе. Но для практики изучения вышло вполне интересно.
#tricks