python--type,object,元类,__new__关系

版权声明:本博客大部分文章均为原创文章,转载请标明出处哟,可以关注我个人公众号获取数据和代码~ https://blog.csdn.net/qq_27056805/article/details/86554961

上篇文章中通过代码方式,重点讲解了:

  1. __new__和__init__之间的关系,前者是用来创建类实例,后者用来初始化类实例,它两配合使用,才完整生成一个类实例。
  2. object和type之间的关系,前者负责继承这块工作,后者负责类型定义这块工作。即所有的对象都起源于object,所有的对象最终都是type这个类型。

本文将重点介绍元类和元类的创建。

1.什么是元类

元类是创建类的类。如何理解这句话,先看以下代码:

class B():
    pass
b=B()
print(b.__class__)
print(B.__class__)
print(object.__class__)
#打印情况:
<class '__main__.B'>
<class 'type'>
<class 'type'>

上述代码中b是由类B构建的,因此b的类型(通过__class__属性查看)是<class ‘main.B’>,而后面B和object的类型都是type,同理,这说明B和object都是由type这个类创建的,即type可以用来创建类。
能够创建类的类,我们称作元类,type就是最原始的一个元类。

2.type如何创建类

首先声明:type在python中有两个身份:
1.type当做函数用,同__class__属性作用相同,返回对象的类型
2.type当做类用,是元类,用于创建其它的类。

下面是当做类用。
语法:

type(类名称字符串,类继承的元组,类的属性/函数字典)

三个的参数含义和类型都在上面规定了。下面代码用type类创建了一个类A,并为类A创建了一个name属性和一个show函数(注意不是shows函数,尽管定义的时候是shows)

def shows(self,name):
    print(name)
#用type类创建类A
A=type("A",(object,),{'name':"bob",'show':shows})
aa=A()
print(aa.name)
aa.show("wangwu")

##输出结果
bob
wangwu

3.自定义元类

默认情况下,所有类都是由type元类创建,当然也可以自定义元类,这样该类的__class__属性就不是type了,而是该自定义元类。
语法:自定义元类必须要显示继承于type类。

class XXMetaClass(type):
	pass

4.设置类的元类为自定义元类

class XXClass(object,metaclass=XXMetaClass):
	pass

5.实例演练

下面代码中定义了一个元类TMetaclass,和三个普通类,且这三个普通类都是通过该元类生成的。由下面的打印结果可知,元类的__new__函数返回的值正是各个类。也就是说,在元类中是通过__new__函数生成类的。

class TMetaclass(type):
    def __new__(cls, name, bases, attrs):
        print("__new__参数:",cls, name, bases, attrs,'\n')
        
        print("__new__返回类型: ",type.__new__(cls, name, bases, attrs),'\n')
        return type.__new__(cls, name, bases, attrs)#生成相应的类,并返回

class Test1(dict,metaclass=TMetaclass):
    def __init__(self, **kw):
       super(T, self).__init__(**kw)   
    def p(self):
        print("ppp")
    pass

class Test2(Test1):
    pass

class Test3(Test2):
    pass
    
#结果打印:
__new__参数: <class '__main__.TMetaclass'> Test1 (<class 'dict'>,) {'__module__': '__main__', '__qualname__': 'Test1', '__init__': <function Test1.__init__ at 0x000002F08653E8C8>, 'p': <function Test1.p at 0x000002F08653E7B8>, '__classcell__': <cell at 0x000002F0864BA1C8: empty>} 

__new__返回类型:  <class '__main__.Test1'> 

__new__参数: <class '__main__.TMetaclass'> Test2 (<class '__main__.Test1'>,) {'__module__': '__main__', '__qualname__': 'Test2'} 

__new__返回类型:  <class '__main__.Test2'> 

__new__参数: <class '__main__.TMetaclass'> Test3 (<class '__main__.Test2'>,) {'__module__': '__main__', '__qualname__': 'Test3'} 

__new__返回类型:  <class '__main__.Test3'> 

4.类实例的生成过程

分为两个阶段:
1.类的生成:由元类生成;
2.实例的生成:由上述生成的类接着生成。

具体描述

结合上一篇文章中,我们总结出生成一个类实例的全部过程:
1.类首先查找内部__metaclass__属性是否被自定义元类赋值,若赋值则准备用该自定义元类生成类,否则用type作为元类生成类;
2.解释器调用该元类的__new__函数(该函数为静态函数),并将要实例化的类中定义的各种属性传递给该函数固定的四个参数:其中cls是该元类本身,name是要被实例化的类的类名,bases是该类父类组成的元组,attrs则是该类{属性名:属性值,函数名:函数对象}组成的字典。
3.最终通过type类生成该类,并返回。
4.该类生成后,调用类中的__new__函数(该函数是静态函数)创建该类的实例,并返回该实例;
5.该实例接着调用它的__init__函数初始化实例,这样一个完整的实例就被生成出来了。

5,自定义元类的核心

由于是元类构建了类,因此若要更改某些固定类(str,int等)的用法,就必须在元类中做文章了。而元类的核心是__new__函数,自然在该函数内做文章。比如可以通过atrris字典为元类添加新的属性和函数,或改变以往的属性或函数等。这样的改变会传播到所有用该元类创建的类中。

总结:
__new__函数:
1.在元类中该函数用来构建类本身;
2.在类中,该函数用来构建类实例;

6. 类函数调用方式

def A():
	def show(self,name):
		print(name)
a=A()
#我们的调用方式:
a.show("hello")
#实际解释器的调用方式,这个a实例填充了self这个参数的位置
A.show(a,"hello")

参考文献:
1.深刻理解Python中的元类(metaclass)以及元类实现单例模式
2. 道生一,一生二
3. 一篇文章让你彻底搞清楚Python中self的含义

猜你喜欢

转载自blog.csdn.net/qq_27056805/article/details/86554961