鱼C论坛

 找回密码
 立即注册
查看: 1378|回复: 3

[已解决]041讲__new__魔法方法各种不理解

[复制链接]
发表于 2017-12-7 08:47:21 | 显示全部楼层 |阅读模式
10鱼币
以下是小甲鱼老师上课的例子:
  1. class CapStr(str):
  2.     def __new__(cls,string):
  3.         string=string.upper()   
  4.         return str.__new__(cls,string)
复制代码


这是我自己的问题与理解,请问理解正确吗?不正确以及不理解的地方请帮忙回答,谢谢各位!

1.如果不重写new方法,则new方法默认什么?
个人理解:返回 str.__new__(cls)
2.这段代码在完成什么事情?
个人理解:将大写的string传给下面的init方法
3.那为什么以下代码不能实现?
  1. class CapStr(str):
  2.     def __new__(cls,string):
  3.         string=string.upper()   
  4.         return str.__new__(cls,string)
  5.     def __init(self,string):
  6.         self.x=string

  7. cs=CapStr('I love You')
  8. cs.x
复制代码

不理解
4.在实例化对象的时候为什么输出一段字符?
个人理解:因为这个类只有一个new方法没有init方法,所以只能输出要传给init的string参数
最佳答案
2017-12-7 08:47:22
本帖最后由 铁棍阿童木 于 2017-12-7 10:18 编辑

小甲鱼这里只是举例说明__new__(cls)这个特殊方法的用法。在视频和书中都明确说明了绝大多数情况都不需要去改写这个特殊方法的。只有当类继承自另一个不可变类的时候才需要去改写。
1、class CapStr(str)请注意,这个类继承自 str 类;
2、因此如果你不重写__new__方法的话,任何字符串都没有办法在__init__方法中实现首字母大写的初始化操作;
3、改写完成后必须将改动提交给父类的__new__方法来实现返回,例题中是用: str().__new__(cls, string)来实现的,但是一般最好用super函数来避免菱形继承。

至于你的第二段代码不能实现有两个地方理解有误:
1、__init__少了两个下划线;
2、__new__是用来初始化类,__init__是用来初始化类对象;所以__init__里面的self.x属性是cs的,也就是最初传递进去的I Love You字符串,所以你输出还是原来的样子。
3、只需要输入 cs 并回车就可以看到全部大写后的字符串,这是因为实例化对象 cs 的时候__new__方法除了 cls 参数以外,其他参数都会传递给__init__方法,所以不需要你再写一次了。所有有没有你写的__init__都不影响。

你看下图我的运行结果,第一个是有 __init__的,第二个是没有__init__的。你也可以试试!

最佳答案

查看完整内容

小甲鱼这里只是举例说明__new__(cls)这个特殊方法的用法。在视频和书中都明确说明了绝大多数情况都不需要去改写这个特殊方法的。只有当类继承自另一个不可变类的时候才需要去改写。 1、class CapStr(str)请注意,这个类继承自 str 类; 2、因此如果你不重写__new__方法的话,任何字符串都没有办法在__init__方法中实现首字母大写的初始化操作; 3、改写完成后必须将改动提交给父类的__new__方法来实现返回,例题中是用: str(). ...
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2017-12-7 08:47:22 | 显示全部楼层    本楼为最佳答案   
本帖最后由 铁棍阿童木 于 2017-12-7 10:18 编辑

小甲鱼这里只是举例说明__new__(cls)这个特殊方法的用法。在视频和书中都明确说明了绝大多数情况都不需要去改写这个特殊方法的。只有当类继承自另一个不可变类的时候才需要去改写。
1、class CapStr(str)请注意,这个类继承自 str 类;
2、因此如果你不重写__new__方法的话,任何字符串都没有办法在__init__方法中实现首字母大写的初始化操作;
3、改写完成后必须将改动提交给父类的__new__方法来实现返回,例题中是用: str().__new__(cls, string)来实现的,但是一般最好用super函数来避免菱形继承。

至于你的第二段代码不能实现有两个地方理解有误:
1、__init__少了两个下划线;
2、__new__是用来初始化类,__init__是用来初始化类对象;所以__init__里面的self.x属性是cs的,也就是最初传递进去的I Love You字符串,所以你输出还是原来的样子。
3、只需要输入 cs 并回车就可以看到全部大写后的字符串,这是因为实例化对象 cs 的时候__new__方法除了 cls 参数以外,其他参数都会传递给__init__方法,所以不需要你再写一次了。所有有没有你写的__init__都不影响。

你看下图我的运行结果,第一个是有 __init__的,第二个是没有__init__的。你也可以试试!
11111.png
222222.png
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2017-12-7 20:28:26 | 显示全部楼层
铁棍阿童木 发表于 2017-12-7 10:07
小甲鱼这里只是举例说明__new__(cls)这个特殊方法的用法。在视频和书中都明确说明了绝大多数情况都不需要去 ...

哇,好详细,结合你的答案我自己又尝试了下,觉得自己的理解偏差真得很大,现在看都很尴尬,谢谢你!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2018-5-9 13:43:27 | 显示全部楼层
jle55555 发表于 2017-12-7 20:28
哇,好详细,结合你的答案我自己又尝试了下,觉得自己的理解偏差真得很大,现在看都很尴尬,谢谢你!

我还是不太理解。。。。。你能讲下自己的见解吗?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-3-29 21:21

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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