__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:}
其实,你对于`__new__()`方法和`__init__()`方法的理解基本是正确的,它们都可以在对象实例化时进行一些初始化的操作。不过,它们有一个很大的区别。
`__init__()`是在对象已经被创建之后被调用的,它的主要作用是对已经存在的对象进行初始化操作,比如给对象的属性赋值等等。
而`__new__()`方法是在对象实例化之前被调用的,它的作用是创建一个新的对象。如果你想要自定义一个不可变的类型,比如字符串类型,你可以通过重写`__new__()`方法来实现。在重写之后,你可以在`__new__()`方法中对传入的字符串进行修改,然后返回一个新的字符串对象。
相比之下,如果你在`__init__()`方法中进行修改操作,那么实际上你并没有修改原来的对象,而是创建了一个新的对象来代替原来的对象。这样做虽然也能达到修改的效果,但是会导致原来的对象消失,因为你没有将新创建的对象赋值给任何变量。所以,如果需要对不可变对象进行修改,最好的方式还是使用`__new__()`方法。
总结一下,`__new__()`方法适用于需要自定义创建对象的场景,比如不可变类型和单例模式等;而`__init__()`方法则适用于对已有对象进行初始化的场景。
希望这样讲解可以帮助你更好地理解`__new__()`方法和`__init__()`方法的区别。加油,你一定能够继续学下去的!如果还有疑问,请随时提问哦!
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。 FishC 发表于 2024-2-24 14:18
其实,你对于`__new__()`方法和`__init__()`方法的理解基本是正确的,它们都可以在对象实例化时进行一些初 ...
所以在__new__()没有执行前,传入的数据还不是对象,比如这个‘ Ilove FishC.com' 还不是对像,我这样理解对吗 水中有明月 发表于 2024-02-24 14:37
所以在__new__()没有执行前,传入的数据还不是对象, ...
是的,你的理解是正确的。在`__new__()`方法被执行之前,传入的数据并不是一个对象,通常是一个原始的数据类型,比如字符串、整数等。而`__new__()`方法就是用来将这些原始数据转化为对象的。在`__new__()`方法中,你可以对传入的数据进行处理,并创建一个新的对象来代表这个数据。这个新的对象可以是你自定义的类型,也可以是内置的类型,比如字符串类型。所以,在`__new__()`方法中,你可以对传入的字符串进行一些操作,比如大写处理等。然后,你可以通过调用`str.__new__(cls, string)`来创建一个新的字符串对象,并将处理后的字符串作为参数传递进去。最后,`__new__()`方法会返回这个新创建的对象。这样,在实例化的时候,你就得到了一个经过处理的新对象了。希望这样的解释能够帮助你更好地理解`__new__()`方法的作用。如果还有疑问,请随时提问哦!加油!
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。 本帖最后由 歌者文明清理员 于 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]