前言
類在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'>]