snakeshe 发表于 2017-4-1 13:29:33

43课课上内容求助

class Nint(int):
      def __radd__(self , other):
                return int.__sub__(self , other)

>>> a = Nint(5)
>>> b = Nint(3)
>>> a + b
8
>>> 1 + b
2
视频里说1 + b调用__radd__方法是因为1 没有 __add__方法,那请问1为什么没有__add__方法呢???

冬雪雪冬 发表于 2017-4-1 13:41:24

1有__add__方法,但只是int和int相加的,没有int和Nint相加的。

snakeshe 发表于 2017-4-1 16:48:06

冬雪雪冬 发表于 2017-4-1 13:41
1有__add__方法,但只是int和int相加的,没有int和Nint相加的。

原来如此 谢谢你 真是越学越难啊

snakeshe 发表于 2017-4-1 16:49:56

冬雪雪冬 发表于 2017-4-1 13:41
1有__add__方法,但只是int和int相加的,没有int和Nint相加的。

所以说一定是要相同的一类 才可以使用__add__方法 对吗? 就比如:必须要 两个都是int , 或者两个都是Nint。一个是int 一个是Nint,就会调用__radd__?是这样理解吗?

冬雪雪冬 发表于 2017-4-1 17:08:12

snakeshe 发表于 2017-4-1 16:49
所以说一定是要相同的一类 才可以使用__add__方法 对吗? 就比如:必须要 两个都是int , 或者两个都是Ni ...

不完全是,Nint + int则因为Nint继承了int的__add__,它能够处理Nint和int的相加,就不调用__radd__了。

snakeshe 发表于 2017-4-1 20:16:39

冬雪雪冬 发表于 2017-4-1 17:08
不完全是,Nint + int则因为Nint继承了int的__add__,它能够处理Nint和int的相加,就不调用__radd__了。

>>> class Nint(int):
        def __radd__(self , other):
                        return int.__sub__(self , other)

               
>>> a = Nint(5)
>>> b = Nint(3)
>>> c = 4
>>> a + b
8
>>> c + b
-1
>>> b + c
7
所以 c + b = -1 是因为c是 int,虽然有__add__方法, 但是 b 是 Nint,所以就回调用 __radd___
而 b + c = 7 是因为 b是 Nint 它继承于 int 所以 它有 __ add__方法 ,而且 c 也是 int ,也有 __add__方法,所以可以产生正常的结果。是这样吗?
但是请问 c + b里面 Nint不是也是继承于 int 吗???

冬雪雪冬 发表于 2017-4-1 20:24:56

如果能够左运算就不会右运算。
c + b先尝试c的__add__,但碰到b,做不下去,就反过来用b的__radd__,这回可以了,就返回-1
b + c先尝试b的__add__,Nint的b继承了int的方法other也是int,就可以做加法了,返回7

但是请问 c + b里面 Nint不是也是继承于 int 吗???
是的,但int没有继承Nint的方法,无法与Nint做加法。

bravsheng 发表于 2021-8-7 11:35:12

冬雪雪冬 发表于 2017-4-1 20:24
如果能够左运算就不会右运算。
c + b先尝试c的__add__,但碰到b,做不下去,就反过来用b的__radd__,这回 ...

class Nint(int):
      def __radd__(self , other):
                return int.__sub__(self , other)

class C(int):
      pass

b = Nint(3)
c = C(4)

运行结果:

>>> c+b
7

疑问:c也没有继承Nint的方法,但可以直接与Nint做加法   (·_·?)

冬雪雪冬 发表于 2021-8-7 15:19:19

bravsheng 发表于 2021-8-7 11:35
class Nint(int):
      def __radd__(self , other):
                return int.__sub__(self , o ...

c没有和b相加的方法,b有和int右加的方法。我认为c是继承int的,所以右加的的方法也适用于b,不知这样的理解对不对

bravsheng 发表于 2021-8-7 15:30:23

冬雪雪冬 发表于 2021-8-7 15:19
c没有和b相加的方法,b有和int右加的方法。我认为c是继承int的,所以右加的的方法也适用于b,不知这样的 ...

可是查看到c也有add的方法呀
>>> dir(c)
['__abs__', '__add__', '__and__', '__bool__', '__ceil__', '__class__', '__delattr__', '__dict__', '__dir__', '__divmod__', '__doc__', '__eq__', '__float__', '__floor__', '__floordiv__', '__format__', '__ge__', '__getattribute__', '__getnewargs__', '__gt__', '__hash__', '__index__', '__init__', '__init_subclass__', '__int__', '__invert__', '__le__', '__lshift__', '__lt__', '__mod__', '__module__', '__mul__', '__ne__', '__neg__', '__new__', '__or__', '__pos__', '__pow__', '__radd__', '__rand__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rlshift__', '__rmod__', '__rmul__', '__ror__', '__round__', '__rpow__', '__rrshift__', '__rshift__', '__rsub__', '__rtruediv__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__trunc__', '__xor__', 'as_integer_ratio', 'bit_length', 'conjugate', 'denominator', 'from_bytes', 'imag', 'numerator', 'real', 'to_bytes']
>>>

bravsheng 发表于 2021-8-7 15:41:23

冬雪雪冬 发表于 2021-8-7 15:19
c没有和b相加的方法,b有和int右加的方法。我认为c是继承int的,所以右加的的方法也适用于b,不知这样的 ...

class B(int):
    def __add__(self , other):
      print("调用b的__add__")
      return int.__add__(self , other)

    def __radd__(self , other):
      print("调用b的__radd__")
      return int.__sub__(self , other)

class A(int):
    def __add__(self , other):
      print("调用a的__add__")
      return int.__add__(self , other)      
   
a = A(4)
b = B(3)

执行结果:
>>> 4+b
调用b的__radd__
-1
>>> a+b
调用a的__add__
7
>>> type(a)
<class '__main__.A'>
>>> type(b)
<class '__main__.B'>
>>> type(4)
<class 'int'>
>>>

我的疑惑: (·_·?)
4+b:4和b分别来源与int类和B类,因为类型不同,调用a的add方法没成功,转而调用b的radd的方法。
a+b:a和b分别来源于A,B两个类,但a的add方法可以成功运行!
a,b算同一类型嘛?怎么解释可以更好的理解? >_<

冬雪雪冬 发表于 2021-8-8 12:38:37

bravsheng 发表于 2021-8-7 15:30
可是查看到c也有add的方法呀
>>> dir(c)
['__abs__', '__add__', '__and__', '__bool__', '__ceil__', ...

c是继承int,所以有int和int相加的__add__,但没有和Nint相加的__add__

冬雪雪冬 发表于 2021-8-8 12:46:30

bravsheng 发表于 2021-8-7 15:41
class B(int):
    def __add__(self , other):
      print("调用b的__add__")


4 + b,你理解的正确
a + b,我也不清楚内在的逻辑,从继承关系看,两者都继承于int,可以认为加后右面为其父类或也是继承其父类是可以__add__运算的
>>> A.mro()
[<class '__main__.A'>, <class 'int'>, <class 'object'>]
>>> B.mro()
[<class '__main__.B'>, <class 'int'>, <class 'object'>]

阿奇_o 发表于 2021-8-8 13:35:46

冬雪雪冬 发表于 2021-8-8 12:46
4 + b,你理解的正确
a + b,我也不清楚内在的逻辑,从继承关系看,两者都继承于int,可以认为加后右面 ...

它的逻辑应该是:
因为有继承关系(即使不继承int,也会默认继承object总父类),
所以 + 运算符,先触发 .__add__(), 本类里没有就会按 .mro()的"基类顺序"找方法__add__,找到就用。
找不到,就尝试 找 __radd__() 。

注:这是大概逻辑,具体还涉及运算结果是否为NotImplenment的判断...

冬雪雪冬 发表于 2021-8-8 13:46:37

阿奇_o 发表于 2021-8-8 13:35
它的逻辑应该是:
因为有继承关系(即使不继承int,也会默认继承object总父类),
所以 + 运算符,先触 ...

感谢!

bravsheng 发表于 2021-8-8 14:48:50

冬雪雪冬 发表于 2021-8-8 12:46
4 + b,你理解的正确
a + b,我也不清楚内在的逻辑,从继承关系看,两者都继承于int,可以认为加后右面 ...

谢谢,有点明白了!mro可以能看到继承顺序呀。

bravsheng 发表于 2021-8-8 14:50:49

冬雪雪冬 发表于 2021-8-8 12:38
c是继承int,所以有int和int相加的__add__,但没有和Nint相加的__add__

嗯,明白了

bravsheng 发表于 2021-8-8 14:57:35

阿奇_o 发表于 2021-8-8 13:35
它的逻辑应该是:
因为有继承关系(即使不继承int,也会默认继承object总父类),
所以 + 运算符,先触 ...

谢谢解答!
所以a是往上找到了<class 'int'>的__add__方法吗?   b需要往上找到int类型吗?
可以讲下a+b的实现过程嘛?   
页: [1]
查看完整版本: 43课课上内容求助