鱼C论坛

 找回密码
 立即注册
查看: 800|回复: 5

[已解决]B站第66讲,关于__new__

[复制链接]
发表于 2024-8-20 10:37:21 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
大家好,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'




最佳答案
2024-8-20 10:53:06
本帖最后由 jackz007 于 2024-8-20 12:06 编辑

         代码1实际上是把自己的代码插入到 str . __new__() 的开头,办完自己的私事再把控制转给 str . __new__() 继续执行,不耽误新建对象的操作,代码2是完全重写了一个方法,和新建对象毫无关系。代码1就比较聪明,它并不取代别人,既办了自己想办的事还不耽误本来该干的事。  
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2024-8-20 10:48:36 | 显示全部楼层
你好,鱼油!关于你提到的 `__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 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-8-20 10:53:06 | 显示全部楼层    本楼为最佳答案   
本帖最后由 jackz007 于 2024-8-20 12:06 编辑

         代码1实际上是把自己的代码插入到 str . __new__() 的开头,办完自己的私事再把控制转给 str . __new__() 继续执行,不耽误新建对象的操作,代码2是完全重写了一个方法,和新建对象毫无关系。代码1就比较聪明,它并不取代别人,既办了自己想办的事还不耽误本来该干的事。  
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-8-20 14:54:18 | 显示全部楼层
你看到的只不过是输出一样,其实结果并不一样

你分别看一下这两段代码的 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 类型,这样的意义何在,就像被带了某颜色帽子一样
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-8-20 16:24:32 | 显示全部楼层
jackz007 发表于 2024-8-20 10:53
代码1实际上是把自己的代码插入到 str . __new__() 的开头,办完自己的私事再把控制转给 str . __ ...

好的,非常感谢!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-8-20 16:25:33 | 显示全部楼层
isdkz 发表于 2024-8-20 14:54
你看到的只不过是输出一样,其实结果并不一样

你分别看一下这两段代码的 cs 的类型就知道了

好的,谢谢您
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-12-26 03:57

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表