Почему вызов «магического метода» Python не выполняет преобразование типов, как это было бы для соответствующего оператора? - PullRequest
0 голосов
/ 20 февраля 2019

Когда я вычитаю число с плавающей точкой из целого числа (например, 1-2.0), Python выполняет неявное преобразование типов (я думаю).Но когда я называю то, что я думал, было той же самой операцией, используя магический метод __sub__, она внезапно перестает существовать.

Что мне здесь не хватает?Когда я перегружаю операторы для своих собственных классов, есть ли способ обойти это, кроме явного приведения ввода к тому типу, который мне нужен?

a=1
a.__sub__(2.)
# returns NotImplemented
a.__rsub__(2.)
# returns NotImplemented
# yet, of course:
a-2.
# returns -1.0

Ответы [ 2 ]

0 голосов
/ 20 февраля 2019

@ user2357112 уже хорошо сказал, но нет ничего похожего на пример.

class A:
   def __sub__(self, other):
       print('A.__sub__')
       if not isinstance(other, A):
           return NotImplemented
       return 0

   def __rsub__(self, other):
       print('A.__rsub__')
       if not isinstance(other, A):
           return NotImplemented
       return 0

class B:
   def __sub__(self, other):
       print('B.__sub__')
       if not isinstance(other, B):
           return NotImplemented
       return 0

a1 = A()
a2 = A()
b = B()

a1 - a2
A.__sub__
# 0

Объекты a1 и a2 совместимы (оба типа A), верный результат возвращается.

Далее рассмотрим,

b - a1
B.__sub__
A.__rsub__
# TypeError: unsupported operand type(s) for -: 'B' and 'A'

Объекты b и a1 несовместимы.Сначала пробуется b.__sub__, что возвращает NotImplemented, поэтому пробуется a1.__rsub__, что также возвращает NotImplemented.Итак, TypeError поднято.

Наконец,

a1 - b
A.__sub__
# TypeError: unsupported operand type(s) for -: 'A' and 'B'

На этот раз сначала пробуется a1.__sub__, что возвращает NotImplemented.Теперь, поскольку b.__rsub__ не определено, TypeError повышается.

0 голосов
/ 20 февраля 2019

a - b это не просто a.__sub__(b).Он также пытается b.__rsub__(a), если a не может обработать операцию, а в случае 1 - 2. это операция __rsub__, которая обрабатывает операцию.

>>> (2.).__rsub__(1)
-1.0

Вы запустили a.__rsub__(2.), но это не так __rsub__.Вам нужен правый операнд __rsub__, а не левый операнд.


В оператор вычитания не встроено неявное преобразование типов.float.__rsub__ должен обрабатывать целые вручную.Если вы хотите преобразовать тип в своих собственных реализациях операторов, вам придется обрабатывать это и вручную.

...