__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__
方法,并将self
,age
作为参数。
__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__
有三个参数cls
,age
,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__()
始终是静态方法,即使没有加上静态方法装饰器
- 默认调用父类的
__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')