【python】type和元類

前言

類在Python中是對象
python中用type或者元類定義類對象
類的__new__ 方法用於控制創建對象,創建並返回一個新的對象
類的__init__ 方法用於初始化對象
type(類名,基類元組(可以爲空), 屬性字典)
type(what=className, bases=(object,), dict=attrs)

元類

用於創建類的方法或者類稱爲元類,Python類的默認元類爲type
demoClass.__class__ 即可得到demoClass這個類的元類
元類的作用在於自動攔截類的創建,修改類,並返回修改後的類

自定義元類

class MyMetaClass(type):
	def __new__(cls, name, bases, attrs):
		# 這裏實現類屬性的改寫,然後返回一個新的類
		return type.__new__(cls, name, bases, attrs)

python2中使用元類

class DemoClass(object):
	# name = DemoClass
	# bases = object
	# attrs = DemoClass類中定義的變量,方法等。
	
	__metaclass__=MyMetaClass
	xxxx

python3中使用元類

class DemoClass(object, metaclass=MyMetaClass):
	xxxx

__metaclass__=MyMetaClass在類外面使用將作用於該py模塊的所有類

元類與繼承的區別

類並不能使用元類的屬性,但派生類可以使用基類(繼承類)的屬性。
普通類的屬性查找順序爲,類>object,
派生方式的類的屬性查找順序爲,派生類>基類>基類的基類>object,
元類生成的類的屬性查找順序爲,類>object,

元類衝突

多重繼承過程中由於派生類的元類不是基類的元類的子類,就會造成元類衝突而報錯。

	class Meta1(type):
	    def __new__(cls, *args, **kwargs):
	        return type.__new__(cls, *args, **kwargs)
	
	
	class Meta2(type):
	    def __new__(cls, *args, **kwargs):
	        return type.__new__(cls, *args, **kwargs)
	
	class B(metaclass=Meta1):
	    print('B')
	
	class A(metaclass=Meta2):
	    print('A')
	
	class C(A,B):
	    print('C')
	Traceback (most recent call last):
	  File "E:/GitHub/py3/PerformanceAnalysisReport/graph/demo.py", line 18, in <module>
	    class C(A,B):
	TypeError: metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases

解決方法可以定義一個繼承基類的元類的類作爲派生類的元類。

	class Meta1(type):
	    def __new__(cls, *args, **kwargs):
	        print('meta1')
	        return super().__new__(cls, *args, **kwargs)
	
	
	class Meta2(type):
	    def __new__(cls, *args, **kwargs):
	        print('meta2')
	        return super().__new__(cls, *args, **kwargs)
	
	class Meta(Meta1, Meta2):
	    print('meta')
	    pass
	
	class A(metaclass=Meta1):
	    print('A')
	
	class B(metaclass=Meta2):
	    print('B')
	
	class C(A, B, metaclass=Meta):
	    print('C')
	
	print(type(C))
	print(C.mro())
	# 創建類Meta時輸出
	meta
	
	# 創建類A時輸出
	A
	meta1
	# 創建類B時輸出
	B
	meta2
	# 創建類C時輸出
	C
	meta1
	meta2
	<class '__main__.Meta'>
	[<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章