参考python 类中__init__,__new__,__class__的使用详解
1、python类的__new__()方法:
①、__new__方法用于给类创建实例对象,并且返回这个实例对象;
②、因为给类创建实例对象,所以要传递一个类型对象,惯例称为"cls",代表要实例化的类,此参数在实例化时由python解释器自动提供;
③、创建实例对象时,如"obj = Person('pawarotti')",将先执行__new__(cls, *args, **kwargs)方法在堆栈中构造出一个随机初始化的实例对象,然后__new__()方法返回这个实例对象,接着调用类实例方法__init__(self, *args, *kwargs)并传递实例对象给形参"self",然后执行初始化方法__init__()的函数体,也就是初始化动作;
④、__new__()是实例化时最先调用的方法,一般不要人为地重写该方法;
#-*-encoding:utf-8-*-
# https://www.bbsmax.com/A/1O5Eg81az7/
'''1、类实例对象的构造过程:执行obj=Person('pawarotti')后,首先调用
类方法__new__(cls, *args, **kwargs),python解释器自动将当前类的类型
对象传递给第一个位置实参'cls',关键字实参被赋值给kwargs形参,
其他实参被赋值给args形参,然后返回一个未初始化的实例对象,这一步应该
是在堆或栈中开辟了对象的内存空间并返回地址;
2、<class 'type'>的类型对象包含① 、object基类的实例属性(如__class__
)和方法(如静态方法__new__);② 、type基类的实例属性和方法(如静态
方法__new__)③ 、关联的类的类属性和类方法
3、第一个位置形参若作为类型对象,同时也没有@classmethod修饰的方法,并且调用时也是用"类型对象.方法"的形式
这样的方法更像是类方法而不是实例方法。
4、类的静态方法则由于调用时不会做任何形参绑定,使用上就是个函数
'''
class Person():
def __init__(self, name):
print('执行Person类实例方法__init__()')
self.name = name
'''5、构造方法之所以是个实例方法是因为这里的self实例对象首先
由__new__静态方法生成了,然后才调用__init__实例方法并静默传
生成的实例对象给第一个位置形参'self',在__init__实例方法中
只是对实例对象进行初始化的动作
'''
def __new__(cls, *args, **kwargs):
print('执行Person类的方法__new__()')
#return object.__new__(cls, *args, **kwargs)
'''4、TypeError: object.__new__() takes exactly one argument
(the type to instantiate),喔唷,help(object)的函数签名确实是
__new__(*args, **kwargs),但却提示说只接受一个类型对象
'''
res = object.__new__(cls)
print('object.__new__(cls) returns:', object.__new__(cls))
#这里再次调用__new__(cls)生成一个实例对象但没有返回其引用,
#当对象的引用记数为零时会自动释放
# 打印<__main__.Person object at 0x7f8d2b52ac40>
return res
'''6、基类object的静态方法__new__()其实是import的type类的静态
方法__new__(),类型对象作为第一个位置形参,创建并返回一个实例对象,
随后将调用实例方法__init__()并将该实例对象绑定到其'self'形参
'''
def FakeClsMethod(cls):
print('the invoker obj is: ', cls)
obj=Person('pawarotti')
print('instance obj: ', obj)
'''8、打印<__main__.Person object at 0x7f732c4ea820>,注意到和__new__()方法
中构造的实例对象地址还不一样,说明python3进行了某种调整?'''
#Person.FakeClsMethod()
#TypeError: FakeClsMethod() missing 1 required positional argument: 'cls'
Person.FakeClsMethod(Person) #the invoker obj is: <class '__main__.Person'>
'''7、python3中类型对象也可以调用实例方法,但不会做任何形参绑定,所以需要
手动填入实参;但python2会把调用认为是解绑方法,并报错:
TypeError: unbound method FakeClsMethod() must be called with Person instance
as first argument (got classobj instance instead)
而实例对象调用实例方法,会将实例对象和第一个位置形参(一般取名字"self")绑定;
类型对象调用类方法,会将类型对象和第一个位置形参(一般取名字"cls")绑定;
'''
python3.8执行输出:
haypin@ubt:~/Files$ python3.8 m08022.py
执行Person类的方法__new__()
object.__new__(cls) returns: <__main__.Person object at 0x7f1cfdcf2c40>
执行Person类实例方法__init__()
instance obj: <__main__.Person object at 0x7f1cfdcf2820>
the invoker obj is: <class '__main__.Person'>
haypin@ubt:~/Files$