Raddzor788
@Raddzor788
Изучаю Python

Классы. Принцип работы __add__ с __radd__?

class Commuter5:
    def __init__(self, val):
        self.value = val
    def __add__(self, other):
        return Commuter5(self.value + other)
    def __radd__(self, x):
        return Commuter5(self.value + x)
    def __str__(self):
        return '<Commuter: %s>' % self.value
x = Commuter5(10)
y = Commuter5(20)
z = x + y
print(z)


Недавно начал изучать ООП. Помогите разобраться в этом примере. Мне нужно знать, как это вообще работает. Исправлять ничего не нужно. Я хочу понять принцип. С одной стороны - код понятный и не сложный, но когда я начал смотреть это в debugger, то некоторый момент очень сильно смутили. Если кому не сложно, то пожалуйста, проверьте код на debugger, и объясните.
На сколько я понял(и как показывает в debugger) когда идет z = x + y, то Python пытается сложить сначала внутри метода __add__, self.value, который равен 10, и other,который равен объекту класса . Метод __add__ , как мне известно - не будет это отрабатывать, потому что метод __add__ сработает только, если будет <объект класса> + <число>, крч чтобы объект числа был справа. (тут мне еще момент не понятен, если выше сказанное верно, то почему Python сразу не пошел в метод __radd__ мне не понятно, но да ладно. Если не сложно, объясните и этот момент). Когда в методе __add__ появляется такое выражение, то насколько я понял, Python отправляет это все в метод __radd__, чтобы он отработал этот момент, и там все это успешно происходит, и вот после этого момент для меня начинается полная тьма!!!! Что тут сделала конструкция внутри метода __radd__, а именно 'return Commuter5(self.value + x)' ??. Как показывает debugger - Python снова идет внутрь метода __init__, и там как я понял инициализируется какой-то объект(как мне известно __init__ служит для инициализации объектов класса. Что инициализируется внутри __init__ ,,?? там появляется вот такая запись self: <__main__.Commuter5 object at 0x000001C54CA967D0> val:30)Внимание: все это происходит в Pycharm. Если метод __init__ что-то инициализировал, то где это хранится? по идее же в каком-то экземпляре класса? или я что-то не понимаю? Дальше вообще полный трешь творится. Python опять почему-то идет внутрь метода __radd__, и снова делает return Commuter5(self.value + x), потом идет внутрь __add__ и делает return Commuter5(self.value + other) не понятно почему и на сколько там видно - other по прежнему равен объекту класса
  • Вопрос задан
  • 179 просмотров
Пригласить эксперта
Ответы на вопрос 1
Vindicar
@Vindicar
RTFM!
1. Пытается отработать x + y. Вызывается x.__add__(y) (или, что то же самое, Commuter5.__add__(x, y)).
2. Внутри кода __add__() вычисляется выражение self.value + other. Вызывается self.value.__add__(other)(int.__add__(self.value, other), так как self.value содержит целое число).
3. int понятия не имеет, что такое Commuter5 и как с ним складываться. Его __add__() возвращает NotImplemented. Питон понимает, что от int помощи не дождёшься.
4. Поэтому вызывается other.__radd__(self.value).
5. Внутри этого метода вычисляется выражение self.value + x. В данном случае x - это self.value для первого операнда, т.е. число. self.value - тоже число. int знает, как складываться с другим int, и выражение даёт int.
6. Отрабатывает конструктор Commuter5() внутри __radd__(). Создаётся новый экземпляр класса, и возвращается как результат вызова __radd__().
7. Отрабатывает конструктор Commuter5() внутри __add__(). Результат (ещё один экземпляр Commuter5) возвращается наружу.
8. z присваивается результат, возвращённый вызовом __add__().

По-моему, в коде ошибка, так как в результате у нас окажется, что внутри Commuter5() будет ещё один объект Commuter5(), внутри которого уже будет сумма. Ты можешь проверить это достаточно просто:
print(type(z.value))
Если выведет <class Commuter5 ...> - значит, я прав.
Чтобы это исправить, операторы __add__() и __radd__() должны проверять, что получилось в результате суммирования, и не заворачивать результат в Commuter5() еще раз.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы