关于魔方方法的疑问
class S(str):def __add__(self, other):
return len(self) + len(other)
class S1(str):
def __add__(self, other):
return NotImplemented
class S2(str):
def __radd__(self, other):
return len(self) + len(other)
s = S('FishC')
s1 = S1('Apple')
s2 = S2('Banana')
print('s1+s2:', s1 + s2)
print('s2+s1:', s2 + s1)
print('s + s1:', s + s1)
# print('s1 + s:', s1 + s)
print('s + s2:', s + s2)
print('s2 + s:', s2 + s)
print("s + 'nwu':", s + 'nwu')
print("'nwu' + s:", 'nwu' + s)
# print("s1 + 'nwu':", s1 + 'nwu')
print("'nwu' + s1:", 'nwu' + s1)
print("s2 + 'nwu':", s2 + 'nwu')
print("'nwu' + s2:", 'nwu' + s2)
运行结果如下:
s1+s2: 11
s2+s1: BananaApple
s + s1: 10
s1+s运行错误
s + s2: 11
s2 + s: BananaFishC
s + 'nwu': 8
'nwu' + s: nwuFishC
s1 + 'nwu' 运行错误
'nwu' + s1: nwuApple
s2 + 'nwu': Banananwu
'nwu' + s2: 9
请教各位老师,在魔方方法中学习中,个人理解是,先看左边对象有没有__add__方法, 如果左边对象没有__add__方法,或者返回NotImplemented是,看右边有没有__radd__方法。
但是print("'nwu' + s2:", 'nwu' + s2)这个的结果我不太理解,我以为结果应该是nwuBanana,但是为什么是9呢, 我想着’nwu‘是一个字符串对象,应该有__add__方法啊;比如print("'nwu' + s:", 'nwu' + s)这个结果就是nwuFishC, 好像是符合我理解的。到底我是哪里理解错误呢,请指点。
你的理解基本正确,Python在遇到加法运算符的时候,会首先尝试调用左操作数的__add__方法,如果返回了NotImplemented ,那么就会尝试调用右操作数的__radd__方法。
在你的示例中,当执行'nwu' + s2时,Python 首先尝试调用字符串'nwu'的__add__方法,这个方法期望接收一个字符串作为参数,但接收到的是一个S2类型的对象,因此无法执行加法,返回了NotImplemented 。
然后,Python 会尝试调用s2的__radd__方法,这个方法定义了当它与一个字符串进行加法运算时,应该返回两者的长度之和,因此结果是 9。
至于'nwu' + s ,结果是'nwuFishC' ,是因为'nwu'的__add__方法可以接受s (也就是S类型的对象)作为参数,并返回一个新的字符串。当s是S类型的对象时,由于S类型没有重载__radd__方法,所以直接使用了字符串的__add__方法。
总的来说,当你在两个对象之间使用运算符时,Python 会首先尝试调用左操作数的特殊方法,然后尝试调用右操作数的对应的反向特殊方法。这是 Python 的运算符重载机制决定的。 isdkz 发表于 2023-6-17 23:53
你的理解基本正确,Python在遇到加法运算符的时候,会首先尝试调用左操作数的__add__方法,如果返回了...
您好,还是有点晕,再请教您一下
当执行'nwu' + s2时,Python 首先尝试调用字符串'nwu'的__add__方法,这个方法期望接收一个字符串作为参数,但接收到的是一个S2类型的对象,
'nwu' + s ,结果是'nwuFishC' ,是因为'nwu'的__add__方法可以接受s (也就是S类型的对象)作为参数,
当'nwu’分别与s和s2相加时, 应该首先调用的都是‘nwu'的__add__方法啊,方法应该是一样的,s 和 s2分别是S和S2类型的对象,按您的说法,应该都是返回了 NotImplemented这个才对啊。 wbzxz 发表于 2023-6-18 06:36
您好,还是有点晕,再请教您一下
当执行'nwu' + s2时,Python 首先尝试调用字符串'nwu'的__ad ...
对不起,我在上一次的解答中存在一些不清楚的地方,让我们更深入地理解Python的方法解析顺序和运算符重载机制。
在Python中,当我们对两个对象进行加法操作时,Python会先尝试调用左边对象的 __add__ 方法。如果该方法返回 NotImplemented ,或者该方法不存在,那么Python就会尝试调用右边对象的 __radd__ 方法。
在这个例子中,字符串对象"nwu"的 __add__ 方法期望接收一个字符串作为参数,但在 'nwu' + s2 这个表达式中,它接收到的却是一个 S2 类型的对象。这时,Python会尝试调用 s2 的 __radd__ 方法,也就是 S2 类定义的 __radd__ 方法,它期望接收一个字符串作为参数,并返回两者的长度之和。所以,结果是9。
同样,在 'nwu' + s 这个表达式中,字符串对象"nwu"的 __add__ 方法尝试将 s (也就是 S 类型的对象)作为参数,这时由于 s 也是字符串子类,所以 'nwu' 可以接受 s 作为参数,并且返回两者拼接之后的字符串,所以结果是'nwuFishC'。
所以,总结一下:
· 对于 'nwu' + s2 ,因为's2'( S2 类的对象)不是一个字符串,所以Python无法直接使用 'nwu' 的 __add__ 方法将其作为参数。因此,Python尝试调用 s2 的 __radd__ 方法,并将'nwu'作为参数,返回两者的长度之和,结果是9。
· 对于 'nwu' + s ,由于 s ( S 类的对象)是字符串的子类,所以Python可以使用 'nwu' 的 __add__ 方法将其作为参数,并返回两者拼接之后的字符串,所以结果是'nwuFishC'。 在这个问题中,您的理解是正确的。根据文档,如果左侧对象没有实现 `__add__` 方法,则将使用右侧对象的 `__radd__` 方法。在这种情况下,您会预期结果为 "nwuBanana",但是您得到了 9 作为结果。这是因为类 `S2` 中定义的 `__radd__` 在计算长度之前应用了字符串类型转换。所以,当您执行 `'nwu' + s2` 时,它实际上是 `(str)'nwu' + (str)s2`,即 `'nwu' + 'Banana'`。结果是一个长度为 6 的字符串,加上字符串 `'nwu'` 的长度,总长度为 9。这就是为什么输出是 9 而不是 'nwuBanana'。
求最佳答案{:10_254:} isdkz 发表于 2023-6-18 11:28
对不起,我在上一次的解答中存在一些不清楚的地方,让我们更深入地理解Python的方法解析顺序和运算符重载 ...
class S(str):
def __add__(self, other):
return len(self) + len(other)
class S1(str):
def __add__(self, other):
return NotImplemented
class S2(str):
def __radd__(self, other):
return len(self) + len(other)
S类对象和S2类对象是一样的啊,都是继承str类,为什么说s(S类的对象)是字符串的子类,而's2'(S2类的对象)不是一个字符串呢? sfqxx 发表于 2023-6-18 11:30
在这个问题中,您的理解是正确的。根据文档,如果左侧对象没有实现 `__add__` 方法,则将使用右侧对象的 `_ ...
您好,我还是有些不理解。。
'nwu' + s请问这时使用的是不是'nwu' 的 __add__方法呢?
'nwu' + s2请问为什么不使用'nwu' 的 __add__方法呢? wbzxz 发表于 2023-6-18 14:40
您好,我还是有些不理解。。
'nwu' + s请问这时使用的是不是'nwu' 的 __add__方法呢?
对于表达式 `'nwu' + s`,使用的是 `'nwu'` 的 `__add__` 方法。这是因为在 Python 中,当解释器遇到表达式 `x + y` 时,它会首先尝试调用 `x` 对象的 `__add__` 方法来处理该操作。
而对于表达式 `'nwu' + s2`,并没有使用 `'nwu'` 的 `__add__` 方法。这是因为 `'nwu'` 是字符串类型,而 `s2` 是 `S2` 类的实例,而不是字符串实例。`str` 类已定义了自己的 `__add__` 方法用于字符串拼接,但是 `S2` 类重写了父类 `str` 的 `__add__` 方法,而是定义了 `__radd__` 方法作为右侧加法运算符的处理。由于 `s2` 出现在 `'nwu'` 右边,所以会调用 `s2` 的 `__radd__` 方法。
下面是给出的示例代码的输出结果:
s1+s2: 10
s2+s1: BananaApple
s + s1: FishCApple
s + s2: NotImplemented
s2 + s: 12
s + 'nwu': FishCnwu
'nwu' + s: nwuFishC
'nwu' + s1: nwuApple
s2 + 'nwu': 6
'nwu' + s2: nwuBanana
根据输出结果可知,使用 `+` 运算符时,调用的是各个对象类中相应的魔术方法(如 `__add__`、`__radd__`),从而实现不同的加法操作。 sfqxx 发表于 2023-6-18 16:24
对于表达式 `'nwu' + s`,使用的是 `'nwu'` 的 `__add__` 方法。这是因为在 Python 中,当解释器遇到表达 ...
您好, 在这里我最不理解的是s2是S2类的实例, 不是字符串实例, 所以没有用str类的__add__方法, 但是s是S类的实例,也不是字符串实例啊, 为什么要用str类的__add__方法呢? wbzxz 发表于 2023-6-18 16:42
您好, 在这里我最不理解的是s2是S2类的实例, 不是字符串实例, 所以没有用str类的__add__方法, 但是s是S ...
您好!正如您所说,S类和S2类都是自定义的字符串子类,并不直接继承str类型。然而,在Python中,“+”运算符通常与__add__方法相关联,与对象的实际类型无关。
因此,当我们使用s + s1和s + s2操作时,同样会调用该操作符左侧对象(即第一个参数对象)的__add__方法。在这种情况下,由于S类继承了字符串类型的所有特性,因此可以使用标准的__add__方法。相反,S1类显式地禁止了__add__,导致返回NotImplemented。最后,S2类使用了__radd__方法,它允许反向的加操作,即以字符串为第一个参数。
页:
[1]