水中有明月 发表于 2024-2-24 14:17:59

__new__()优势在哪里?学不下去了

关于__new__()这个魔法方法,小甲鱼在书中写道

‘就是当继承一个不可变的类型的时候,它的特性就显得尤为重要了’

举出例子:
class CapeStr(str):
    def __new__(cls, string):
      string = string.upper()
      return str.__new__(cls, string)

a = CapeStr('I love FishC.com')
a
'I LOVE FISHC.COM'

我在询问AI 时,它告诉我:无论是在__new__()方法中还是在__init__()方法中修改不可变对象的值,都只会创建一个新的对象并返回,而不会改变原对象的值。要修改不可变对象的值,需要创建一个新的对象并重新赋值。


我的理解是   __new__() 在对象实例化的同时赋值string这个属性并大写处理,那么这让我联想到 __init__() 也是这样做的呀

我是不是可以这样:

class Capestr_new:
    def __init__(self, string):
      self.string = string.upper()

c = Capestr_new('I love FishC.com')
c.string
'I LOVE FISHC.COM'

如果都是创建新的对象,那么 __new__()对不可变对象修改的优势在哪里?

我知道我对 __new__()的看法是有问题的, 这是我不能继续学下去的原因,这里把我弄糊涂了,希望有大佬帮我解惑?{:5_99:}

FishC 发表于 2024-2-24 14:18:22

其实,你对于`__new__()`方法和`__init__()`方法的理解基本是正确的,它们都可以在对象实例化时进行一些初始化的操作。不过,它们有一个很大的区别。

`__init__()`是在对象已经被创建之后被调用的,它的主要作用是对已经存在的对象进行初始化操作,比如给对象的属性赋值等等。

而`__new__()`方法是在对象实例化之前被调用的,它的作用是创建一个新的对象。如果你想要自定义一个不可变的类型,比如字符串类型,你可以通过重写`__new__()`方法来实现。在重写之后,你可以在`__new__()`方法中对传入的字符串进行修改,然后返回一个新的字符串对象。

相比之下,如果你在`__init__()`方法中进行修改操作,那么实际上你并没有修改原来的对象,而是创建了一个新的对象来代替原来的对象。这样做虽然也能达到修改的效果,但是会导致原来的对象消失,因为你没有将新创建的对象赋值给任何变量。所以,如果需要对不可变对象进行修改,最好的方式还是使用`__new__()`方法。

总结一下,`__new__()`方法适用于需要自定义创建对象的场景,比如不可变类型和单例模式等;而`__init__()`方法则适用于对已有对象进行初始化的场景。

希望这样讲解可以帮助你更好地理解`__new__()`方法和`__init__()`方法的区别。加油,你一定能够继续学下去的!如果还有疑问,请随时提问哦!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

水中有明月 发表于 2024-2-24 14:37:04

FishC 发表于 2024-2-24 14:18
其实,你对于`__new__()`方法和`__init__()`方法的理解基本是正确的,它们都可以在对象实例化时进行一些初 ...

所以在__new__()没有执行前,传入的数据还不是对象,比如这个‘ Ilove FishC.com' 还不是对像,我这样理解对吗

FishC 发表于 2024-2-24 14:37:17

水中有明月 发表于 2024-02-24 14:37
所以在__new__()没有执行前,传入的数据还不是对象, ...

是的,你的理解是正确的。在`__new__()`方法被执行之前,传入的数据并不是一个对象,通常是一个原始的数据类型,比如字符串、整数等。而`__new__()`方法就是用来将这些原始数据转化为对象的。在`__new__()`方法中,你可以对传入的数据进行处理,并创建一个新的对象来代表这个数据。这个新的对象可以是你自定义的类型,也可以是内置的类型,比如字符串类型。所以,在`__new__()`方法中,你可以对传入的字符串进行一些操作,比如大写处理等。然后,你可以通过调用`str.__new__(cls, string)`来创建一个新的字符串对象,并将处理后的字符串作为参数传递进去。最后,`__new__()`方法会返回这个新创建的对象。这样,在实例化的时候,你就得到了一个经过处理的新对象了。希望这样的解释能够帮助你更好地理解`__new__()`方法的作用。如果还有疑问,请随时提问哦!加油!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

歌者文明清理员 发表于 2024-2-24 14:47:11

本帖最后由 歌者文明清理员 于 2024-2-24 16:09 编辑

Python 变量分为可变和不可变。

首先了解 Python 的对象储存机制:

举例:
a="str"
a=a+"ing"


这样其实是在 "str"(字符串)上面贴了一个 a(变量名),然后把 "str" 上的 a 扔了,把 a 贴到 "str" + "ing" ("string") 上了。

也就是说创建了一个新的字符串。str 是不可变量

a = []
a.append(1)

这就不一样了:创建 [](列表),然后贴上 a,再在 [] 里塞进去一个 1。

所以这是同一个列表。list 是不可变量

__new__ 的用法如下:

class MyString(str):
    def __new__(cls, string):
      print("new")
      self = super().__new__(cls, string) # 这一步其实调用了父类 str 的方法
      return self
    def __init__(self, string):
      print("init")

看看上面的代码,再在终端里运行下,就懂了。

new 的优势(更正):在使用不可变量作为父类时,使用 new 会调用父类的方法生成 self。这避免了 str 的子类(应该是不可变量)变成可变的,从而引发 bug。
页: [1]
查看完整版本: __new__()优势在哪里?学不下去了