鱼C论坛

 找回密码
 立即注册
查看: 3263|回复: 14

关于__new__()的理解

[复制链接]
发表于 2015-8-19 10:17:00 | 显示全部楼层 |阅读模式

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

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

x
   今天看了小甲鱼的视频教程041:构造和析构,有个问题请教大家啊~~
   小甲鱼说当需要继承一个不可变类型的时候,有需要进行修改的时候,就用__new__(),给的例子是:
  1. class CapStr(str):
  2.         def __new__(cls,string):
  3.                 string=string.upper()
  4.                 return string.__new__(cls,string)
复制代码

但是我写成这样也没报错:
  1. class CapStr(str):
  2.         def __new__(cls,string):
  3.                 string=string.upper()
  4.                 return string
复制代码



如何理解str是不可修改的,以及为什么要写成return  string.__new__(cls,string)
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2015-8-19 10:37:46 | 显示全部楼层
有人知道吗??
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-8-20 01:22:34 | 显示全部楼层
1.字符串和元祖类型是不可修改的,
例子如下
  1. >>> f = '1234'
  2. >>> f[0] = '5'
  3. 会报错
复制代码

2.上面好像写错了
是return str.__new__(cls,string)
因为 返回基类的__new__方法  不容易出错。
当和其他的魔法方法一起使用容易造成死循环
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 2 反对 1

使用道具 举报

 楼主| 发表于 2015-8-21 09:34:14 | 显示全部楼层
  1. class CapStr(str):
  2.         def __new__(cls,string):
  3.                 string=string.upper()
  4.                 return string
复制代码

  1. >>> c=CapStr('I Love Fishc.com')
  2. >>> c
  3. 'I LOVE FISHC.COM'
  4. >>>
复制代码

这样子算不算是改变了字符串,把字符串改成全部大写?
非常感谢你哈,每次都是你给我解答~~
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-8-21 17:27:29 | 显示全部楼层
本帖最后由 戴宇轩 于 2015-8-21 17:30 编辑

这样会造成无限递归
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-8-21 17:32:05 | 显示全部楼层
你可能想说str.__new__(cls, string)

把第三行去掉,然后传入一个数字,对比一下两个结果, 然后你就应该懂了~
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-8-23 15:37:16 | 显示全部楼层
戴宇轩 发表于 2015-8-21 17:32
你可能想说str.__new__(cls, string)

把第三行去掉,然后传入一个数字,对比一下两个结果, 然后你就应 ...

大神,你知道那个CLS有什么用和具体含义吗?
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-8-24 15:02:29 | 显示全部楼层
本帖最后由 戴宇轩 于 2015-8-24 15:13 编辑
Geek_yy 发表于 2015-8-23 15:37
大神,你知道那个CLS有什么用和具体含义吗?


str.__new__(cls, string)中,这里cls是这个类自身(Capstr)(其实我觉得跟self没啥区别),是用str.__new__实例化cls,并传入参数(string)
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

发表于 2015-8-29 22:30:06 | 显示全部楼层
本帖最后由 netikid 于 2015-8-29 23:02 编辑

3#楼的这种解释是不对的。即使换成列表也是不行的。
比如说:
  1. class A(list):
  2.         def __new__(cls,list1):
  3.                 list1 = list1.sort()
  4.                 return list.__new__(cls,list1)
复制代码

实例化后
  1. a = A([4,5,6,3,2,1])
复制代码

则a = [1, 2, 3, 4, 5, 6];
然而如果是修改__init__就不行。

解答楼主的问题,这里的__new__方法需要一个实例化对象做返回值。比如说
  1. class S:
  2.         pass
复制代码

则用这种语句
  1. c = S.__new__(S)
复制代码

相当于将类S实例化。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-8-29 22:59:04 | 显示全部楼层
戴宇轩 发表于 2015-8-21 17:32
你可能想说str.__new__(cls, string)

把第三行去掉,然后传入一个数字,对比一下两个结果, 然后你就应 ...

非常简单明了地道出了区别。一个返回字符串一个返回参数本身。感谢。想请教一下,那这个要看需求呢,还是说后者就是一种不好的做法呢?
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-8-30 00:10:35 | 显示全部楼层
学习了。。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-9-1 09:36:34 | 显示全部楼层
学习了!!!
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-4-7 09:23:05 | 显示全部楼层
Geek_yy 发表于 2015-8-23 15:37
大神,你知道那个CLS有什么用和具体含义吗?

你知道就说呀,别光说,其实我也等答案
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-5-9 12:51:44 | 显示全部楼层
风逝无痕 发表于 2018-4-7 09:23
你知道就说呀,别光说,其实我也等答案

类比self
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-5-9 13:22:23 | 显示全部楼层
戴宇轩 发表于 2015-8-21 17:32
你可能想说str.__new__(cls, string)

把第三行去掉,然后传入一个数字,对比一下两个结果, 然后你就应 ...

我按照你说的做了,输出还是数字啊?是不是我搞错了,能否进一步解释下
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-2-17 07:15

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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