B站第66讲,关于__new__
大家好,B站看到了66讲,关于__new__有一个疑问,还请懂的同学帮忙解答一下。我的问题是,既然代码1和代码2的结果是一样的,那么代码1的代码“super().__new__(cls, string)”的作用是什么呢,是不是有点多余呢,直接像代码2一样“return string”不是更简洁吗?谢谢大家!
代码1:
class CapStr(str):
def __new__(cls, string):
string = string.upper()
return super().__new__(cls, string)
cs = CapStr("FishC")
cs
'FISHC'
cs.lower()
'fishc'
cs.capitalize()
'Fishc'代码2:
class CapStr(str):
def __new__(cls, string):
string = string.upper()
return string
cs = CapStr("FishC")
cs
'FISHC'
cs.lower()
'fishc'
你好,鱼油!关于你提到的 `__new__` 方法的问题,确实是一个很有趣的点。我们来详细解释一下。
首先,`__new__` 是一个特殊方法,用于创建并返回一个新的实例。它在对象实例化的过程中首先被调用,然后才是 `__init__` 方法。对于不可变类型(如 `str`、`int` 等),`__new__` 方法尤其重要,因为这些类型的实例一旦创建就不能修改。
### 代码1和代码2的区别
#### 代码1:
class CapStr(str):
def __new__(cls, string):
string = string.upper()
return super().__new__(cls, string)
#### 代码2:
class CapStr(str):
def __new__(cls, string):
string = string.upper()
return string
### 解释
1. **代码1**:
- `string = string.upper()`:将输入的字符串转换为大写。
- `return super().__new__(cls, string)`:调用父类 `str` 的 `__new__` 方法来创建一个新的字符串实例。
2. **代码2**:
- `string = string.upper()`:同样将输入的字符串转换为大写。
- `return string`:直接返回转换后的字符串。
### 为什么代码1更好?
虽然代码2看起来更简洁,但它实际上没有遵循正确的对象创建流程。具体来说:
- **代码1** 确保了 `CapStr` 类的实例是通过 `str` 类的 `__new__` 方法创建的,这样可以保证所有 `str` 类的行为和特性都被正确继承。
- **代码2** 直接返回了一个字符串,这个字符串虽然是大写的,但它并不是通过 `CapStr` 类创建的实例。因此,严格来说,`cs` 不是一个 `CapStr` 的实例,而只是一个普通的字符串。
### 举个例子
假设你想在 `CapStr` 类中添加一些额外的方法或属性,如果你使用代码2的方式,这些方法或属性将无法在返回的字符串上使用,因为它们并不是 `CapStr` 的实例。
class CapStr(str):
def __new__(cls, string):
string = string.upper()
return super().__new__(cls, string)
def shout(self):
return self + "!!!"
cs = CapStr("FishC")
print(cs.shout())# 输出:FISHC!!!
如果你用代码2的方式,`cs` 就没有 `shout` 方法了。
### 总结
虽然代码2看起来更简洁,但它没有遵循正确的对象创建流程,可能会导致一些意想不到的问题。代码1虽然稍微复杂一点,但它确保了 `CapStr` 类的实例是通过 `str` 类的 `__new__` 方法创建的,从而继承了所有 `str` 类的行为和特性。
希望这个解释对你有帮助!如果还有其他问题,欢迎继续提问!
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。 本帖最后由 jackz007 于 2024-8-20 12:06 编辑
代码1实际上是把自己的代码插入到 str . __new__() 的开头,办完自己的私事再把控制转给 str . __new__() 继续执行,不耽误新建对象的操作,代码2是完全重写了一个方法,和新建对象毫无关系。代码1就比较聪明,它并不取代别人,既办了自己想办的事还不耽误本来该干的事。 你看到的只不过是输出一样,其实结果并不一样
你分别看一下这两段代码的 cs 的类型就知道了
>>> class CapStr(str):
... def __new__(cls, string):
... string = string.upper()
... return super().__new__(cls, string)
...
>>>
>>> cs = CapStr("FishC")
>>>
>>> type(cs)
<class '__main__.CapStr'>
>>>
>>>
>>>
>>> class CapStr(str):
... def __new__(cls, string):
... string = string.upper()
... return string
...
>>>
>>> cs = CapStr("FishC")
>>> type(cs)
<class 'str'>
>>>
所以你知道为什么要用 super 了没,super 只是帮你寻找父类的实例化方法来创建出一个实例,并不会影响到实例的类型,而你直接返回 string 的话,string 原本是什么类型实例化出来的对象就是什么类型了
由 CapStr 实例化出来的对象却不是 CapStr 类型,这样的意义何在,就像被带了某颜色帽子一样{:5_97:} jackz007 发表于 2024-8-20 10:53
代码1实际上是把自己的代码插入到 str . __new__() 的开头,办完自己的私事再把控制转给 str . __ ...
好的,非常感谢! isdkz 发表于 2024-8-20 14:54
你看到的只不过是输出一样,其实结果并不一样
你分别看一下这两段代码的 cs 的类型就知道了
好的,谢谢您
页:
[1]