传统类的创建
'''单例模式的类'''
class MySingleton:
__obj = None
__init_flag = True
def __new__(cls, *args, **kwargs):
if cls.__obj == None:
cls.__obj = object.__new__(cls)
'''
如果是return cls,则返回这个类的一个实例
这里调用的是实例的私有变量__obj,即返回None
'''
return cls.__obj
def __init__(self,name):
if MySingleton.__init_flag:
print("init...")
self.name = name
MySingleton.__init_flag = False
#a = MySingleton("aa")#只能够调用一次,调用后出触发初始化flag,使得__new__返回一个空的object类
#print(a)
#b = MySingleton("bb")
#print(b)
通过type创建类
type创建类的格式:类名 = type(‘类名’,(父类,),{‘方法名’:方法的内存地址})
def func(self): #创建方法
print("hello {0}".format(self.name))
>>> A=type("A",(MySingleton,),{"talk":func})
>>> a=A("test")
init...
>>> a.talk()
hello test
>>> B=type("B",(object,),{"talk":func})
>>> b=B("test")
>>> b.talk()
hello test
总结:类 是由 type 类 实例化产生的
- __new__方法
new方法是类自带的一个方法,可以重构,__new__方法在实例化的时候也会执行,并且先于__init__方法之前执行.
class Foo(object):
def __init__(self,name):
self.name = name
print("Foo __init__")
def __new__(cls, *args, **kwargs):
print("Foo __new__",cls, *args, **kwargs)
return object.__new__(cls)
f = Foo("test")
#输出
Foo __new__ <class '__main__.Foo'> test #执行了new方法
Foo __init__ #执行了__init__方法
new方法作用
作用:所有对象都是通过new方法来实例化的,new里面调用了init方法,所以在实例化的过程中先执行的是new方法,而不是init方法。
①重构__new__方法
class Foo(object):
def __init__(self,name):
self.name = name
print("Foo __init__")
def __new__(cls, *args, **kwargs):
print("Foo __new__",cls, *args, **kwargs)
f = Foo("shuaigaogao") #实例化
#输出
Foo __new__ <class '__main__.Foo'> shuaigaogao
由上面的例子看出,没有执行__init__方法
②重构__new__方法,并继承父类的__new__方法
class Foo(object):
def __init__(self,name):
self.name = name
print("Foo __init__")
def __new__(cls, *args, **kwargs): #cls相当于传入类Foo
print("Foo __new__",cls, *args, **kwargs)
return object.__new__(cls) #继承父类的__new__方法,这边必须以返回值的形式继承
f = Foo("shuaigaogao")
#输出
Foo __new__ <class '__main__.Foo'> shuaigaogao
Foo __init__
由上面不难看出,大多数情况下,你都不要去重构你的__new__方法,因为你父类中已经有__new__方法了,已经帮你写好了怎么去创建类,如果你重写的话,就会覆盖父类的里面的__new__方法。但是你重构可以增加一点小功能,但是你覆盖了以后还是需要继承父类回来,要不然你的这个实例就创建不了。
- 补充
new() 通常会返回该类的一个实例,但有时也可能会返回其他类的实例,如果发生了这种情况,则会跳过对 init() 方法的调用。
class nonZero(int):
def __new__(cls,value):
return super().__new__(cls,value) if value != 0 else None
def __init__(self,skipped_value):
print("__init__()")
super().__init__()
a=nonZero(-12) #会返回此类的实例,调用init
b=nonZero(0) #会返回None,即非此类
print(type(a)) #此类
print(type(b)) #非此类
'''
#输出
__init__()
<class '__main__.nonZero'>
<class 'NoneType'>
'''
使用场景
我想对我自己写的一些类进行定制,就在它实例化之前就进行定制,就可以用到__new__方法,new方法就是用来创建实例的,重构new方法,必须以返回值的形式继承父类的new方法。
①需求:我在创建对象时候,同时创建一个类变量
class Foo(object):
def __init__(self,name):
self.name = name
print("Foo __init__")
def __new__(cls, *args, **kwargs): #cls相当于是传入的类名Foo
cls.name = "shuaigaogao" #创建对象是定义静态变量
print(cls.name)
return object.__new__(cls) #继承父类的__new__方法
f = Foo("shuaigaogao")
print(Foo.name)
"""
#输出
shuaigaogao
Foo __init__
shuaigaogao
"""
__metaclass__方法
- metaclass作用
类 是由 type 类实例化产生
那么问题来了,类默认是由 type 类实例化产生,type类中如何实现的创建类?类又是如何创建对象?
答:类中有一个属性 metaclass,其用来表示该类由 谁 来实例化创建,所以,我们可以为 metaclass 设置一个type类的派生类,从而查看 类 创建的过程。
# -*- coding: utf-8 -*-
"""
Created on Mon Feb 22 17:54:46 2021
@author: daicong
"""
class MyType(type):
def __init__(self,*args,**kwargs):
print("Mytype __init__",*args,**kwargs) #2、其次被执行
def __call__(self, *args, **kwargs):
print("Mytype __call__", *args, **kwargs) #3、其次被执行
obj = self.__new__(self)
print("obj ",obj,*args, **kwargs) #5、其次被执行
print(self) #6、其次被执行
self.__init__(obj,*args, **kwargs)
return obj
def __new__(cls, *args, **kwargs):
print("Mytype __new__",*args,**kwargs) #1、首先执行new
return type.__new__(cls, *args, **kwargs) #返回实例化类,调用init
print('here...')
class Foo(object,metaclass=MyType):
def __init__(self,name):
self.name = name
print("Foo __init__") #7、最后被执行
def __new__(cls, *args, **kwargs):
print("Foo __new__",cls, *args, **kwargs) #4、其次被执行
return object.__new__(cls) #返回实例化类,调用init
f = Foo("Alex") #输出1、2、3、4、5、6、7
print("f",f)
print("fname",f.name)
'''
#输出
here...
1、Mytype __new__ Foo (<class 'object'>,) {'__module__': '__main__', '__qualname__': 'Foo', '__init__': <function Foo.__init__ at 0x0000019A54F22280>, '__new__': <function Foo.__new__ at 0x0000019A54F221F0>}
2、Mytype __init__ Foo (<class 'object'>,) {'__module__': '__main__', '__qualname__': 'Foo', '__init__': <function Foo.__init__ at 0x0000019A54F22280>, '__new__': <function Foo.__new__ at 0x0000019A54F221F0>}
3、Mytype __call__ Alex
4、Foo __new__ <class '__main__.Foo'>
5、obj <__main__.Foo object at 0x0000019A54F0C310> Alex
6、<class '__main__.Foo'>
7、Foo __init__
#上面是在实例化的阶段输出的
f <__main__.Foo object at 0x0000019A54F0C310>
fname Alex
'''
'''
执行顺序
类的生成 调用 顺序依次是 new --> init --> call