fc5igm 发表于 2021-6-15 13:20:34

关于__new__方法

def test(x):
    x=float(x)
    y=x*3.14
    return y

class CapString(str):
    def __new__(cls,string):
      test(string)
      return test(string)
    def __init__(self,x):
      self.string=self

    def printstr(self):
      print(f"类中self的值:{self}")


>>> a=CapString('3.14')
>>> a.string
Traceback (most recent call last):
File "<pyshell#280>", line 1, in <module>
    a.string
AttributeError: 'float' object has no attribute 'string'
我不太明白为什么会报错。a不是成为了一个实例对象吗?为什么又会被认为是个浮点数?
如果我想要在__new__中执行一些指令,而不仅仅是引用其他类的__new__属性,应该怎么做?

Twilight6 发表于 2021-6-15 13:28:48


__new__ 的返回值是返回给 __init__ 的,将实例化后的对象返回给 __init__

而此时你将 test() 函数调用后的返回值设置为 __new__ 的返回值

那么此时 __new__ 返回的是什么对象,__init__ 就接收什么对象

显然你此时传入的是 '3.14' 字符串的实例对象,经过 test 函数后返回 y 是浮点型

则你写的 CapString 类返回的永远是 float 实例对象,而不是 CapString 类的实例对象

你调用 string 是CapString 类的属性,而不是 float 的, float 类没有 string 属性所以报错

fc5igm 发表于 2021-6-15 13:37:22

Twilight6 发表于 2021-6-15 13:28
__new__ 的返回值是返回给 __init__ 的,将实例化后的对象返回给 __init__

而此时你将 test() 函数调 ...

我不是很明白。假设我要在new中做计算的话,必然要做int或者float转化。而转化后的值也就必然是int类或者float的实例对象是吗?那是否就是说,我在__new__下,除了引用其他类的__new__,其实是死活都做不了任何l的数据处理的?

kogawananari 发表于 2021-6-15 13:43:50

为什么要在new方法里做计算   可以定义其他构造方法 以from开头就行类似于 datetime.forISOstring通过字符串创建时间日期可以用这个 不一定非得 datetime()

另外就是str类super init方法什么也不能做 如果定义init 不要去调用super init而new方法最好去调用super new

hrpzcf 发表于 2021-6-15 13:44:42

__new__中单纯返回浮点数的话,该CapString的实例a跟CapString是没有关系的
这样
def test(x):
    x=float(x)
    y=x*3.14
    return y

class CapString(float):
    def __new__(cls,string):
      return super().__new__(cls, test(string))
    def __init__(self,x):
      self.string=self

    def printstr(self):
      print(f"类中self的值:{self}")

a = CapString("3.14")

print(a.string)

print(isinstance(a, float), isinstance(a, CapString))

Twilight6 发表于 2021-6-15 13:46:11

fc5igm 发表于 2021-6-15 13:37
我不是很明白。假设我要在new中做计算的话,必然要做int或者float转化。而转化后的值也就必然是int类或者 ...



为什么不直接将这个运算放置于 __init__ 呢

Twilight6 发表于 2021-6-15 13:48:37

fc5igm 发表于 2021-6-15 13:37
我不是很明白。假设我要在new中做计算的话,必然要做int或者float转化。而转化后的值也就必然是int类或者 ...



每个魔法方法都有其对应的职责

对不负责这个职责的魔法方法强加给对方,这不是在做吃力不讨好的事情嘛

fc5igm 发表于 2021-6-15 14:03:01

Twilight6 发表于 2021-6-15 13:48
每个魔法方法都有其对应的职责

对不负责这个职责的魔法方法强加给对方,这不是在做吃力不讨好的事 ...

那我如果想要输入的第一个参数设为一个字符串,第二个参数设为一个整数,第三个参数设为一个浮点数,应该怎么做?
__new__只能返回一个参数吧?

Twilight6 发表于 2021-6-15 14:08:07

fc5igm 发表于 2021-6-15 14:03
那我如果想要输入的第一个参数设为一个字符串,第二个参数设为一个整数,第三个参数设为一个浮点数,应该 ...



__new__ 设置的参数都会传递给 __init__ ,你在 new 设置参数相当于在 __init__ 设置

fc5igm 发表于 2021-6-15 14:09:14

Twilight6 发表于 2021-6-15 13:48
每个魔法方法都有其对应的职责

对不负责这个职责的魔法方法强加给对方,这不是在做吃力不讨好的事 ...

是否说__new__方法所做的事情,实际上就是类似于list(),str(),int(),float()这些函数?
另外,请问我在类中是以上函数都一律不能调用吗?
class CapString(str):


    def __init__(self,x,y,z):
      self.str=str(x)
      self.int=int(y)
      self.float=float(z)

    def printstr(self):
      print(f"类中self的值:{self}")
a=CapString('abc','10','3.14')
Traceback (most recent call last):
File "D:\python\works\test.py", line 16, in <module>
    a=CapString('abc','10','3.14')
TypeError: decoding str is not supported

Twilight6 发表于 2021-6-15 14:13:32

fc5igm 发表于 2021-6-15 14:09
是否说__new__方法所做的事情,实际上就是类似于list(),str(),int(),float()这些函数?
另外,请问我在 ...


是否说__new__方法所做的事情,实际上就是类似于list(),str(),int(),float()这些函数?

应该说 list(),str(),int(),float() 都是通过 __new__ 来进行实例对象

另外,请问我在类中是以上函数都一律不能调用吗?

这完全没有冲突,不可变类型参数继承重写一般重写 __new__ 而不重写 __init__

fc5igm 发表于 2021-6-15 14:15:58

hrpzcf 发表于 2021-6-15 13:44
__new__中单纯返回浮点数的话,该CapString的实例a跟CapString是没有关系的
这样

懂了。谢谢。
不过如果我想设置多个呢?
比如参数a是str,参数b是int
还有,既然是引用的str类的__new__方法,那也就代表str的__new__必然是对str的参数进行了一定处理的。
我们可以仿照它,自行设定其他的处理方式吗?

fc5igm 发表于 2021-6-15 14:19:26

Twilight6 发表于 2021-6-15 14:13
应该说 list(),str(),int(),float() 都是通过 __new__ 来进行实例对象




class CapString(str):


    def __init__(self,x,y,z):
      self.str=str(x)
      self.int=int(y)
      self.float=float(z)

    def printstr(self):
      print(f"类中self的值:{self}")
a=CapString('abc','10','3.14')

Traceback (most recent call last):
File "D:\python\works\test.py", line 11, in <module>
    a=CapString('abc','10','3.14')
TypeError: decoding str is not supported
如果说”没有冲突“,那我有些不太明白,这里为什么会报错。或者说,表达以上函数的意思,请问应该怎么写才是正确的?

Twilight6 发表于 2021-6-15 14:31:53

fc5igm 发表于 2021-6-15 14:19
如果说”没有冲突“,那我有些不太明白,这里为什么会报错。或者说,表达以上函数的意思,请问应该怎 ...



我刚刚试着运行了下你的代码,报错的主要原因似乎不是因为 str、int、float 待我再研究研究

fc5igm 发表于 2021-6-15 14:34:55

Twilight6 发表于 2021-6-15 14:24
换种通俗点的解释看看你能不能理解:__new__ 作用就是将 self 是什么告诉给 __init__ 并把定义的参数 ...

我忘记删继承了。抱歉。
然后还有另一个问题。我们对__new__方法的使用,就只能是调用其他类的__new__吗?
难道就不能仿照例如str,list这些类,编写自己的__new__吗?

Twilight6 发表于 2021-6-15 14:36:38

fc5igm 发表于 2021-6-15 14:19
如果说”没有冲突“,那我有些不太明白,这里为什么会报错。或者说,表达以上函数的意思,请问应该怎 ...


因为继承了 str 类,在创建实例前,传入参数还是按照__new__ 的来进行传入,而因为 str 类的第二个参数为 encoding 编码参数

所以你此时 CapString('abc','10','3.14') ,相当于 encoding = '10' ,因为没有 10 这种编码所以导致报错

Twilight6 发表于 2021-6-15 14:44:33

fc5igm 发表于 2021-6-15 14:34
我忘记删继承了。抱歉。
然后还有另一个问题。我们对__new__方法的使用,就只能是调用其他类的__new__吗 ...


你若是想完完全全写个自己的类,应该需要写 c 语言代码

否则若你的类进行不继承,则无论如何都是默认继承 object 基类

即: class A:
    pass

等价于:
class A(object):
    pass

fc5igm 发表于 2021-6-15 15:10:49

本帖最后由 fc5igm 于 2021-6-15 15:13 编辑

Twilight6 发表于 2021-6-15 14:44
你若是想完完全全写个自己的类,应该需要写 c 语言代码

否则若你的类进行不继承,则无论如何都是 ...

class Test(list):
    def __new__(cls,*x):
      print(x)
      return list.__new__(cls,x)
    def __init__(self,*x):
      self.L=self


>>> a=Test('a','b','c')
('a', 'b', 'c')
>>> a
[]
>>> a.L
[]
请问这里返回的为什么是个空值?
页: [1]
查看完整版本: 关于__new__方法