鱼C论坛

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

[已解决]Python零基础入门,043将课后作业,动动手1,我这么做跟答案相比有什么问题?

[复制链接]
发表于 2020-5-18 21:59:31 | 显示全部楼层 |阅读模式

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

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

x
题目:定义一个单词(Word)类继承自字符串,重写比较操作符(参考自学:Python 魔法方法详解),当两个 Word 类对象进行比较时,根据单词的长度来进行比较大小。

我的做法用了__init__方法来初始化,也能够实现。但是答案中说,必须要用到__new__方法。那么,我这么做会出现什么问题?

我的做法:

class Word(str):
    def __init__(self, x):
        #如果输入的是空格,就报错
        #如果去掉收尾两端的空格之后,字符串内部有空格的情况
        #然后就是其他
        if x == ' ':
            print('输入错误,不能为空格')
        elif ' ' in x.strip():
            self.x = x.strip().split()[0]
            self.length = len(self.x)
        else:
            self.x = x
            self.length = len(self.x)

    def __lt__(self, other):
        return self.length < other.length

    def __le__(self, other):
        return self.length <= other.length

    def __eq__(self, other):
        return self.length == other.length
   
    def __ne__(self, other):
        return self.length != other.length

    def __gt__(self, other):
        return self.length > other.length
   
    def __ge__(self, other):
        return self.length >= other.length

小甲鱼老师给的答案
class Word(str):
'''存储单词的类,定义比较单词的几种方法'''

    def __new__(cls, word):
        # 注意我们必须要用到 __new__ 方法,因为 str 是不可变类型
        # 所以我们必须在创建的时候将它初始化
        if ' ' in word:
            print "Value contains spaces. Truncating to first space."
            word = word[:word.index(' ')] #单词是第一个空格之前的所有字符
        return str.__new__(cls, word)

    def __gt__(self, other):
        return len(self) > len(other)
    def __lt__(self, other):
        return len(self) < len(other)
    def __ge__(self, other):
        return len(self) >= len(other)
    def __le__(self, other):
        return len(self) <= len(other)

最佳答案
2020-5-18 22:30:42
好鱼怕冷 发表于 2020-5-18 22:08
感谢,我测试得可能还不够。我再试试看。

可否帮忙用我写的那段代码来举个反例?

你的代码直接重新了__init__
并没有用到super(),如果你用super()来继承str原来的__init__就会报错
而如果你重写__new__
用super()继承你父类原本的__new__就不会报错
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2020-5-18 22:06:10 | 显示全部楼层
1. __new__ 是在一个对象实例化的时候所调用的第一个方法
2. 它的第一个参数是这个类,其他的参数是用来直接传递给 __init__ 方法
3. __new__ 决定是否要使用该 __init__ 方法,因为 __new__ 可以调用其他类的构造方法或者直接返回别的实例对象来作为本类的实例,如果 __new__ 没有返回实例对象,则 __init__ 不会被调用
4. __new__ 主要是用于继承一个不可变的类型比如一个 tuple 或者 string

对于 字符串、元组、整型 这些不可变对象,我们重写__init__是无法起到作用的,只有重写__new__才能起到自定义的作用
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-5-18 22:08:36 | 显示全部楼层
本帖最后由 好鱼怕冷 于 2020-5-18 22:14 编辑
Twilight6 发表于 2020-5-18 22:06
对于 字符串、元组、整型 这些不可变对象,我们重写__init__是无法起到作用的,只有重写__new__才能起到 ...


感谢,我测试得可能还不够。我再试试看。

可否帮忙用我写的那段代码来举个反例?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-5-18 22:30:42 | 显示全部楼层    本楼为最佳答案   
好鱼怕冷 发表于 2020-5-18 22:08
感谢,我测试得可能还不够。我再试试看。

可否帮忙用我写的那段代码来举个反例?

你的代码直接重新了__init__
并没有用到super(),如果你用super()来继承str原来的__init__就会报错
而如果你重写__new__
用super()继承你父类原本的__new__就不会报错
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-5-18 22:37:34 | 显示全部楼层
Twilight6 发表于 2020-5-18 22:30
你的代码直接重新了__init__
并没有用到super(),如果你用super()来继承str原来的__init__就会报错
而 ...

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

使用道具 举报

发表于 2020-5-18 22:39:10 | 显示全部楼层
好鱼怕冷 发表于 2020-5-18 22:37
了解了,非常感谢!


加油吧 别客气~
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-1-21 08:56

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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