关于__new__我本来以为我懂了,结果并没有。。。
class C2F(float):"摄氏度转换为华氏度"
def __new__(cls, arg=0.0):
return float.__new__(cls, arg * 1.8 + 32)
def __init__(self,value):
print (value)
a = C2F(32)
print (a) 杨东明 发表于 2021-7-15 15:18
没懂__new__(cls,arg*1.8 + 32),第二个数据到底起的啥作用??print 不是相当于设置的__str__方法,第二 ...
没懂__new__(cls,arg*1.8 + 32),第二个数据到底起的啥作用?
计算好华氏度传给父类的 __new__ 后调利用父类 float 的 __new__ 来创建实例对象,简单来说就是创建了 用 float 类创建了个实例
print 不是相当于设置的__str__方法,第二个数据就相当于设置__str__??
__str__方法其实是在 print() 对象时调用,这里 print(value) 是调用 value 对象的 __str__ 而不是 C2F 类的 __str,但是因为 C2F 类是继承 float 的,所以也相当于是调用 float 的 __str__
还有就是可不可以解释一下继承父类,继承这些int,float啥的没理解到?
继承父类,子类保留父类的方法和属性,但是若你在字类中重写同名方法,会覆盖了父类的方法导致失去原有父类该同名方法的功能,但是你可以在同名方法中调用父类的该方法来保留父类原有的功能
int.__new__,float.__new__描述不都是返回一个实例对象吗??
不是的,__new__ 本质就是一个方法,也可以说是函数,因为在类中我们称为方法,又因为在 Python 中前后双下划线的方法被称为魔法方法,有特殊的功能和作用。这里 int.__new__,float.__new__ 返回的是实际上就是 int、float 的 __new__ 方法 的内存地址
__new__被调用时开辟一片内存空间,将一个变量引用这片内存空间就是返回一个实例对象的意思吗???
是的,__new__ 开辟内存,返回实例对象
运行结果:32 89.6
这个__new__不是应该返回的是实例对象吗??我是这么理解的,a= C2F(32),首先是__new__启用,更改数据,完成后相当于a = C2F(89.6)来设置实例对象,这时__init__启用,传入的value值为89.6,但是运行print(value)打印的32???还有就是a不是一个实例对象吗?打印出来为啥是一个数?? {:9_220:} __new__不是给函数分配内存的吗, 杨东明 发表于 2021-7-14 21:29
运行结果:32 89.6
这个__new__不是应该返回的是实例对象吗??我是这么理解的,a= C2F(32),首先是__ ...
是呀,__new__ 主要作用是开辟内存创建类的实例,以及将该实例对象和定义的参数都传递给 __init__。
另外,一个数也是一个实例呀,你忘记 type() 返回的时候都是什么 <class 'float'>、<class 'int'> 了么~
Twilight6 发表于 2021-7-14 21:42
是呀,__new__ 主要作用是开辟内存创建类的实例,以及将该实例对象和定义的参数都传递给 __init__。
...
我也没懂。。。。
大佬,我改了一下
class C2F(float):
"摄氏度转换为华氏度"
def __new__(cls, arg=0.0):
print("=="*32)
return type(float.__new__(cls, arg * 1.8 + 32))
def __init__(self,value):
print("++" * 32)
print (value)
print("++" * 32)
a = C2F(32)
print (a)
输出的结果是:
================================================================
<class '__main__.C2F'>
调试代码发现,他都没进去__init__()
Twilight6 发表于 2021-7-14 21:42
是呀,__new__ 主要作用是开辟内存创建类的实例,以及将该实例对象和定义的参数都传递给 __init__。
...
然后,我又改了一下
class C2F(float):
"摄氏度转换为华氏度"
def __new__(cls, arg=0.0):
print("==" * 32)
return float.__new__(cls, arg * 1.8 + 32)
def __init__(self,value):
print("**"*32)
print (value)
self = value
print("**" * 32)
a = C2F(32)
print("--" * 32)
print (a)
这样改了self后, 发现结果还是89.6?这是为什么? 本帖最后由 阿奇_o 于 2021-7-15 12:15 编辑
a = C2F(0)意味着 __new__首先被调用,生成和返回相应的 实例对象(即 self),并传入 __init__(self, value) 的self ,
也就是 __new__ 总是先于 __init__ ,不然就没有 self (相关变量和内存没有开辟出来,没法做任何事) ,
另外一点是 __new__的参数 arg 就是a = C2F(0) 中的 0 ,这0 同时也传给 __init__的value参数。
还有一点是 print(x) 实际上,是调用 x对象的特殊方法__str__() , 即 x.__str__()
故你若要 “初始化”时,就看到 转化后的 华摄氏度,那就 可以直接 print(self),即相当于 print(self.__str__())
而 self 就是 __new__() 生成和返回的 转化后的float数据类型
>>> class c2f(float):
def __new__(cls, arg=0.0):
return float.__new__(cls, arg * 1.8 + 32)
def __init__(self, value):
print(value)
>>> a = c2f(0)
0
>>> type(a)
<class '__main__.c2f'>
>>> print(a)
32.0
>>> a.__str__()
'32.0'
>>> class c2f(float):
def __new__(cls, arg=0.0):
return float.__new__(cls, arg * 1.8 + 32)# 调用float父类的__new__创建对象方法,返回一个转换为华氏度的浮点数
def __init__(self, value):
print(self) # self 就是 由__new__() 先生成的实例对象,然后传给 __init__()
print(self.__str__())
print(value)
>>> b = c2f(0)
32.0
32.0
0
>>> c = c2f(10)
50.0
50.0
10 阿奇_o 发表于 2021-7-15 12:11
a = C2F(0)意味着 __new__首先被调用,生成和返回相应的 实例对象(即 self),并传入 __init__(self, va ...
那为何我在 __init__()中
self= value
外面在print(a)得到结果还是89.6? Twilight6 发表于 2021-7-14 21:42
是呀,__new__ 主要作用是开辟内存创建类的实例,以及将该实例对象和定义的参数都传递给 __init__。
...
没懂__new__(cls,arg*1.8 + 32),第二个数据到底起的啥作用??print 不是相当于设置的__str__方法,第二个数据就相当于设置__str__??我感觉把__new__拿掉,唯一有影响的就是print (a)。还有就是可不可以解释一下继承父类,继承这些int,float啥的没理解到。。我百度也似懂非懂得,int.__new__,float.__new__描述不都是返回一个实例对象吗?? Twilight6 发表于 2021-7-14 21:42
是呀,__new__ 主要作用是开辟内存创建类的实例,以及将该实例对象和定义的参数都传递给 __init__。
...
__new__被调用时开辟一片内存空间,将一个变量引用这片内存空间就是返回一个实例对象的意思吗??? 本帖最后由 阿奇_o 于 2022-1-2 17:37 编辑
杨东明 发表于 2021-7-15 15:18
没懂__new__(cls,arg*1.8 + 32),第二个数据到底起的啥作用??print 不是相当于设置的__str__方法,第二 ...
其实你要先明白,背后它有很多“默认”会去执行的方法,
如 即使 你不写任何,单单写 class MyClass: pass
那么,当 obj = MyClass() , 也一样 会先调用 __new__() , 再 __init__() 等,只是 调用的是 其最终父类object类的__new__() 和 __init__() 以及打印是调用__str__()
但 你 class C2F(float): ...就是继承float类,同时也继承object这个最大的总父类。
当 你 自己 “重写”__new__或__init__或__str__的特殊方法时, 就会 优先调用你写的,而不再往上找父类的,
如 class C2F(float): ... 你直接继承float类,并调用了它的float.__new__(cls, ...) 于是它就按这个执行并返回给 你写的__init__(self, ...)
至于参数的问题,__new__的 cls参数是固定的,且必须是放在第一个(这种叫“静态类方法”,知道怎么写就行了) arg只是个形参的名字,
你可以换成value或任意合适唯一的名字,对应 先用类构造对象的实参,如 C2F(10)里的10,或 MyClass(10) ,
只不过你调用时,写 C2F(..)它直接提示和显示的形参是 __int__的形参名,你不能写别的形参名。。 比如,
>>> class c2f(float):
def __new__(cls, value=0):
return float.__new__(cls, value*1.8+32)
def __init__(self, value):
print(self)
print(value)
>>> a = c2f(10)
50.0
10
>>> b = c2f(value=20)
68.0
20
>>> c = c2f(arg=20) # 报错,你必须 用 __init__里定义的形参。即使你把__new__的形参改为叫 arg , 也会报错。
Traceback (most recent call last):
File "<pyshell#10>", line 1, in <module>
c = c2f(arg=20)
TypeError: __new__() got an unexpected keyword argument 'arg'
>>>
由此可见,__new__的参数,除了 固定的cls,其他参数 都来自 __init__的参数。
嗯,这个我也是 新发现:__new__的参数,除了固定的cls,其他参数 都来自 __init__的参数。{:10_297:}
嗯,我应该讲明白了。。{:10_266:}
-------------
补充:2022年1月2日17:26:59
现在仔细看看,这里关于参数的说法,其实是错误的。应该是 除cls外,__new__的其他参数会传给__init__。
这样就要求,当使用关键字参数时,必须它们所定义的形参名要相同。
否则,无法成功创建实例(这时__new__的参数错误),或无法完成初始化(这时__init__的参数错误)。
阿奇_o 发表于 2021-7-15 15:59
其实你要先明白,背后它有很多“默认”会去执行的方法,
如 即使 你不写任何,单单写 class MyClass:...
第一个def __new__(cls,arg),我大概明白,但是第二个__new__(cls,arg*1.8 + 32)他的第二个参数我没懂。。arg*1.8 +32他是怎么被print出来了?? 阿奇_o 发表于 2021-7-15 15:59
其实你要先明白,背后它有很多“默认”会去执行的方法,
如 即使 你不写任何,单单写 class MyClass:...
这个返回的float.__new__(cls,arg*1.8+32)算实例对象的啥,a =c2f(10)def __new__调用,然后再调用float.__new__(cls,arg*1.8 +32),这个float的__new__开辟一片内存空间,但是第二个数据没有传给__init__,就是打印时才体现 阿奇_o 发表于 2021-7-15 15:59
其实你要先明白,背后它有很多“默认”会去执行的方法,
如 即使 你不写任何,单单写 class MyClass:...
__new__作用不是开辟内存空间,返回实例对象吗,开辟返回起作用的是第一个new函数还是父类的new函数?? 本帖最后由 阿奇_o 于 2021-7-15 22:54 编辑
杨东明 发表于 2021-7-15 16:28
__new__作用不是开辟内存空间,返回实例对象吗,开辟返回起作用的是第一个new函数还是父类的new函数??
实例对象的确可以近似理解为“内存空间”,但这不是关键,关键你要理解它 被创造出来的过程……
我再补充一点吧,__new__ 必须 “正确地返回某个实例对象”(通常是父类的或其本类的 ),
像你 return type(...) 那就有问题了。导致__init__找不到self实例,故__init__根本没用执行下去。
另外,我觉得你对“重写”的概念都不理解,我多说也没用。。 你自己找文档、找例子,慢慢琢磨吧。 Twilight6 发表于 2021-7-16 10:05
计算好华氏度传给父类的 __new__ 后调利用父类 float 的 __new__ 来创建实例对象,简单来说就是创 ...
难受,刚才回复打字打了十分钟
写了一堆解释,结果按到鼠标返回键
直接白写,上面重写了,描述更简洁些了
Twilight6 发表于 2021-7-16 10:07
难受,刚才回复打字打了十分钟
写了一堆解释,结果按到鼠标返回键
懂了大佬,解释的挺好的{:9_231:} 阿奇_o 发表于 2021-7-15 15:59
其实你要先明白,背后它有很多“默认”会去执行的方法,
如 即使 你不写任何,单单写 class MyClass:...
感谢{:9_231:}
页:
[1]
2