object.__new__

__new__

__new__主要负责创建实例对象

class Person(object):
    def __new__(cls, *args, **kw):
        return super().__new__(cls)
    def eat(self):
        print('eat something!')

class Person(object):
    def eat(self):
        print('eat something!')

1.为什么__new__的第一个参数是cls而不是self。因为调用__new__的时候,实例对象还没有被创建,__new__是一个静态方法。第一个参数cls表示当前的class
2.绝大多数时间不需要我们实现__new__方法,python已经帮我们实现:使用父类的__new__()方法来创建对象并返回。所以上述的代码是等价的。

__new____init__的参数关系

__new__方法如果返回cls的对象(return super().__new__(cls)),则对象的__init__方法将自动被调用,相同的参数*args和**kwargs将被传入__init__方法。也既是说__new____init__方法共享同名的参数,除了第一个从cls变成了self
如果__new__没有返回实例对象,则__init__方法不会被调用。

class Person(object):
    def __new__(cls, age): 
            print(f"__new__:age:{age}")
            return super().__new__(cls) 
            
    def __init__(self, age): 
        print(f"__init__:age:{age}")
        self.age = age
p = Person(100)
__new__:age:100
__init__:age:100

在调用Person(100)的时候,__new__中的age被赋值为100,__new__结束后会自动调用__init__,并把age传入给__init__

__new____init__参数多

class Person(object):
    def __new__(cls, age): 
        print(f"__new__:age:{age}")
        return super().__new__(cls) 
            
    def __init__(self): 
        print(f"__init__:age:{age}")
        self.age = age
p = Person(100)
__new__:age:100
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: __init__() takes 1 positional argument but 2 were given

如果我们在__new__中有传入age,而在__init__中没有传入age则会报错:__init__定义时只给了一个固定位置的参数self但是却给了两个参数。很显然是__new__方法直接调用了__init__方法,并将selfage作为参数。

__new____init__参数少

class Person(object):
    def __new__(cls, age): 
        print(f"__new__:age:{age}")
        return super().__new__(cls)
            
    def __init__(self,age, name): 
        print(f"__init__:age:{age}")
        self.age = age
>>> p = Person(100)
__new__:age:100
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: __init__() missing 1 required positional argument: 'name'

实例初始化本质是向__new__中传参

class Person(object):
    def __new__(cls, age, name): 
        print(f"__new__:age:{age}")
        return super().__new__(cls)
            
    def __init__(self,age): 
        print(f"__init__:age:{age}")
        self.age = age
>>> p = Person(100)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: __new__() missing 1 required positional argument: 'name'

同样的道理,如果__init__有三个参数clsage,name,而我们在初始化时(p = Person(100))只给了一个age参数,则会报错。所以没有打印print(f"__new__:age:{age}")
这说明我们在初始化对象时Person(100)的参数,都会先经过__new__方法。

只用__new__而不用__init__来实例化对象实例

class Person(object):
    def __new__(cls, age):
        print('__new__() called.')
        obj = super().__new__(cls)
        obj.age = age
        return obj

a = Person(100)
a.age # 100

当然这种方法是不建议的,我们通常使用以下方法:

class Person(object):
    def __init__(self, age):
        self.age = age
a = Person(100)
a.age # 100

这种既我们常用的定义类写的方法,其实完整的写法是:

class Person(object):
    def __new__(cls, *args, **kwargs):
        return super().__new__(cls)
    def __init__(self, age):
        self.age = age
a = Person(100)
a.age # 100

参考:
https://www.codevoila.com/post/68/new-and-init-in-python

super()

class Person(object):
    def __new__(cls, age): 
        # return object.__new__(cls)
        # return super(Person, cls).__new__(cls)
        return super().__new__(cls) 
            
    def __init__(self, age): 
        self.age = age
Person(100)

object.__new__(cls) 调用父类来创建对象实例
return super().__new__(cls) super()方法返回的既是object对象
return super(Person, cls).__new__(cls) super实际传入了两个参数,第一个是本类的类型(Person),第二个是类型(cls),cls既父类的类

在类的继承中,__init__方法里,我们通常写的是super(类名,self),而这里是super(类名,cls),从self变成cls的原因是,要调用父类的__new__方法,这时还没有对象实例产生。

应用

__new__中判断参数

class Person(object):
    def __new__(cls, age): 
        if age>100:
            return "年龄age需小于100,对象未创建"
        else:
            return super().__new__(cls) 
    def __init__(self, age): 
        self.age = age

Person(200)

'年龄age需小于100,年龄age需小于200,对象未创建'

__init__中判断参数

class Person(object):
    def __new__(cls, age): 
        print("对象已经创建")
        return super().__new__(cls) 
            
    def __init__(self, age): 
        if age>100:
            print("wrong age,参数初始化失败")
        else:
            self.age = age
     
p = Person(200)
对象已经创建
wrong age,参数初始化失败


p.age

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Person' object has no attribute 'age'

使用__new____init__的区别是一个在创建对象之前判断,一个在创建对象之后判断

参考:
https://docs.python.org/3/reference/datamodel.html#object.new
https://www.python.org/download/releases/2.2/descrintro/#cooperation

object.__new__(cls[, ...])
创建一个类的实例.

class A(object):
    def __new__(cls):
        return object.__new__(cls)

__init__有一个参数self,就是这个__new__返回的实例,__init__在__new__的基础上可以完成一些其它初始化的动作,__init__不需要返回值

1.详解

1.__new__()负责创建实例化对象,__init__()负责初始化(设置属性和方法)
2.__new__()始终是静态方法,即使没有加上静态方法装饰器

  1. 默认调用父类的__new__()方法来创建实例,python中所有的类都继承object.不可调用自身的__new__方法,这样会造成死循环,因为会执行自己的__new__()方法
class Foo(object):
    def __new__(cls,*args,**kwagrs):  # cls指代当前类
        return super().__new__(cls,*args,**kwagrs)  # 默认调用父类的__new__()方法
        # return Foo.__new__(object,*agrs,**kwagrs)  # 会再跳到第二行,死循环
        # return 123  # print(Foo(),type(obj))  # 打印结果:123 <class 'int'>,返回的是什么就是构造了什么累

1.1 如果父类中没有,则继续追溯到祖先类

class A(object):
    pass

class B(A):
    pass

class C(B):
    def __new__(cls,*args,**kwargs):
        return super().__new__(cls, *args,**kwargs)

# return B.__new__(cls, *args,**kwargs) 发现没有,则继续往上找A
# return A.__new__(cls, *args,**kwargs)  # 发现没有继续往上找object
# return object.__new__(cls, *args,**kwargs)  # object类中有

1.3 通过__new()__可以返回其他类的实例

class Foo(object):
    def __new__(cls,*args,**kwagrs):
        return object.__new__(cls,*args,**kwagrs)
    
    def __init__(self,name):
        self.name = name

class Bar(object):
    def __new__(cls,*agrs,**kwagrs):
        return object.__new__(Foo,*agrs,**kwagrs)
    
bar = Bar()
print(type(bar)) #foo其实是Stranger类的实例。

2.__new__()__init__()
先执行__new__创建实例,再执行__init__()设置属性和方法

class A:
	def __init__(self, name):
		print('执行 __init__')
		self.name = name

	def __new__(cls, *args, **kw):
		print('执行 __new__)
		return object.__new__(cls)  # 这里和使用super()方法是一样的

a = A('wang')
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值