面向对象【day08】:类的起源与metaclass(二)

本节内容

1、概述

2、类的起源

3、__new__方法

4、__metaclass__方法

一、概述

   前面我们学习了大篇幅的关于类,通过类创建对象,那我们想知道这个类到底是怎么产生的呢?它的一切来源是什么?还有对象,对象是通过什么方法创建的,现在我们一头雾水,行的,下面我们就来揭开类的面纱,看看类和对象到底是怎么创建的,通过什么创建的。

二、类的起源

2.1 传统创建类

1
2
3
4
5
class  Foo( object ):
     def  __init__( self ,name):
         self .name  =  name
 
=  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.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__}) 
=  Foo( "shuaigaogao" )   #创建对象
f.talk()
 
#输出
hello shuaigaogao

总结:类 是由 type 类 实例化产生的

值得注意的是,新式类的写法,在继承父类那边,你继承一个父类后面就要加一个逗号,加逗号,它就把它当做一个元组,不加逗号,就是一个值了

三、__new__方法

3.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 )
 
=  Foo( "shuaigaogao" )
 
#输出
Foo __new__ < class  '__main__.Foo' > shuaigaogao   #执行了new方法
Foo __init__   #执行了__init__方法

3.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)
 
=  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
16
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__方法,这边必须以返回值的形式继承
 
=  Foo( "shuaigaogao" )
 
#输出
Foo __new__ < class  '__main__.Foo' > shuaigaogao
Foo __init__

由上面不难看出,大多数情况下,你都不要去重构你的__new__方法,因为你父类中已经有__new__方法了,已经帮你写好了怎么去创建类,如果你重写的话,就会覆盖父类的里面的__new__方法。但是你重构可以增加一点小功能,但是你覆盖了以后还是需要继承父类回来,要不然你的这个实力就创建不了。

3.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__方法
 
=  Foo( "shuaigaogao" )
print (Foo.name)
 
#输出
shuaigaogao
Foo __init__
shuaigaogao

四、__metaclass__方法

4.1 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 )
 
=  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

创建过程如下:

4.2 执行顺序

类的生成 调用 顺序依次是 __new__ --> __init__ --> __call__

metaclass 详解文章:猛击这里 得票最高那个答案写的非常好

作者:罗阿红 出处:http://www.cnblogs.com/luoahong/ 本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。

转载于:https://www.cnblogs.com/luoahong/p/9895485.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值