【python】-- 类的创建、__new__、__metaclass___
类的创建
前面的随笔都是关于类的知识,通过类创建对象,那这个类到底是怎么产生的呢?
1、 传统创建类
1 2 3 4 5 | class Foo( object ): def __init__( self ,name): self .name = name f = Foo( "shuaigaogao" ) |
f 是通过 Foo 类实例化的对象,其实,不仅 f 是一个对象,Foo类本身也是一个对象,因为在Python中一切事物都是对象,按照一切事物都是对象的理论:obj对象是通过执行Foo类的构造方法创建,那么Foo类对象应该也是通过执行某个类的 构造方法 创建。
1 2 | print ( type (f)) #输出:<class '__main__.Foo'> 表示:f 对象由Foo类创建 print ( type (Foo)) #输出:<class 'type'> 表示:Foo类对象由 type 类创建 |
所以,f对象是Foo类的一个实例,Foo类对象是 type 类的一个实例,即:Foo类对象 是通过type类的构造方法创建
2 、type创建类
说明: type创建类的格式,类名 = type('类名',(父类,),{'方法名':方法的内存地址})
1 2 3 4 5 6 7 8 9 10 11 12 13 | def func( self ): #创建方法 print ( "hello {0}" . format ( self .name)) def __init__( self ,name): #创建构造方法 self .name = name #通过type创建类,如果是经典类的话则写成:Foo = type("Foo",(),{"talk":func,"__init__":__init__}) Foo = type ( "Foo" ,( object ,),{ "talk" :func, "__init__" :__init__}) f = Foo( "shuaigaogao" ) #创建对象 f.talk() #输出 hello shuaigaogao |
总结:类 是由 type 类 实例化产生的
值得注意的是,新式类的写法,在继承父类那边,你继承一个父类后面就要加一个逗号,加逗号,它就把它当做一个元组,不加逗号,就是一个值了
__new__方法
1 、概念
new方法是类自带的一个方法,可以重构,__new__方法在实例化的时候也会执行,并且先于__init__方法之前执行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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( "shuaigaogao" ) #输出 Foo __new__ < class '__main__.Foo' > shuaigaogao #执行了new方法 Foo __init__ #执行了__init__方法 |
2、 new方法作用
作用:所有对象都是通过new方法来实例化的,new里面调用了init方法,所以在实例化的过程中先执行的是new方法,而不是init方法。
①重构__new__方法
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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__方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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 |
由上面不难看出,大多数情况下,你都不要去重构你的__new__方法,因为你父类中已经有__new__方法了,已经帮你写好了怎么去创建类,如果你重写的话,就会覆盖父类的里面的__new__方法。但是你重构可以增加一点小功能,但是你覆盖了以后还是需要继承父类回来,要不然你的这个实力就创建不了。
3、使用场景
我想对我自己写的一些类进行定制,就在它实例化之前就进行定制,就可以用到__new__方法,new方法就是用来创建实力的,重构new方法,必须以返回值的形式继承父类的new方法。
①需求:我在创建对象时候,同时创建一个类变量
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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这个属性叫做元类,它是用来表示这个类是由谁来帮他实例化创建的,说白了,就是相当于自己定制一个类。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | class MyType( type ): def __init__( self , * args, * * kwargs): print ( "Mytype __init__" , * args, * * kwargs) def __call__( self , * args, * * kwargs): print ( "Mytype __call__" , * args, * * kwargs) obj = self .__new__( self ) print ( "obj " ,obj, * args, * * kwargs) print ( self ) self .__init__(obj, * args, * * kwargs) return obj def __new__( cls , * args, * * kwargs): print ( "Mytype __new__" , * args, * * kwargs) return type .__new__( cls , * args, * * kwargs) class Foo( object ,metaclass = MyType): #python3统一用这种 #__metaclass__ = MyType #python2.7中的写法 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( "shuaigaogao" ) print ( "f" ,f) print ( "fname" ,f.name) #输出 Mytype __new__ Foo (< class 'object' >,) { '__new__' : <function Foo.__new__ at 0x0000025EF0EFD6A8 >, '__init__' : <function Foo.__init__ at 0x0000025EF0EFD620 >, '__qualname__' : 'Foo' , '__module__' : '__main__' } Mytype __init__ Foo (< class 'object' >,) { '__new__' : <function Foo.__new__ at 0x0000025EF0EFD6A8 >, '__init__' : <function Foo.__init__ at 0x0000025EF0EFD620 >, '__qualname__' : 'Foo' , '__module__' : '__main__' } Mytype __call__ shuaigaogao Foo __new__ < class '__main__.Foo' > obj <__main__.Foo object at 0x0000025EF0F05048 > shuaigaogao < class '__main__.Foo' > Foo __init__ f <__main__.Foo object at 0x0000025EF0F05048 > fname shuaigaogao |
创建过程如下:
总结:
类的生成 调用 顺序依次是 __new__ --> __init__ --> __call__
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步