元類及其原理

2022-02-16 12:43:42 字數 3999 閱讀 8219

在python中,一切都是物件,那麼類肯定也是乙個乙個物件

如果類是物件的話,那他一定是由乙個例項化得到,這個類就叫做元類。也就是說產生類的類,叫做元類

class person:

def __init__(self,name):

self.name=name

def score(self):

print('分數是100')

p=person('nick')

# a=person

# p1=a('nick')

# print(p1.name)

#如何找元類?

# print(type(p))

#同理:type類是產生所有類的元類

# print(type(person))

print(type(dict))

print(type(list))

print(type(str))

print(type(object))

print(type(type))

上述結構都為,也就是說,在一般情況下,元類為type。type是乙個內建的元類,所有的類都是有type例項化得到

class+類名,會把類構造出來,但是,實際上則是元類例項化產生類這個物件。

我們也可以用type來直接產生類,而不用class關鍵字

type() 掉用類的__init__方法

type(object_or_name, bases, dict)

object_or_name:類的名字,是個字串

bases:是它的所有父類,基類

dict:命名空間,

那麼我們就可以定義乙個簡單的person類

def __init__(self,name):

self.name=name

person=type('person',(object,),)

我們也可以用exec()方法來實現最後字典的輸入

l={}

exec('''

school='school'

def __init__(self,name):

self.name=name

def score(self):

print('分數是100')

''',{},l)

person=type('person',(object,),l)

自定義元類,來控制類的產生,可以控制類名,可以控制類的繼承父類,控制類的命名空間自定義元類必須繼承type,再由自定義類產生類,這樣的自定義類都叫元類

class mymeta(type):

# def __init__(self,*args,**kwargs):

def __init__(self,name,bases,dic):

# self 就是person類

# print(name)

# print(bases)

# print(dic)

#練習一:加限制 控制類名必須以sb開頭

if not name.startswith('sb'):

raise exception('類名沒有以sb開頭')

class sb_person(object,metaclass=mymeta):

school='雄英高中'

def __init__(self,name):

self.name=name

def score(self):

print('分數是100')

如果上述**類名不以sb開頭,則會丟擲'類名沒有以sb開頭'異常

同樣我們也可以辦到讓類必須新增注釋

查詢注釋的方法為類名._doc_

class mymeta(type):

def __init__(self,name,bases,dic):

print(self.__dict__['__doc__'])

doc=self.__dict__['__doc__']

if not doc:

# 沒有加注釋

raise exception('你的類沒有加注釋')

#metaclass=mymeta 指定這個類生成的時候,用自己寫的mymeta這個元類

class person(object,metaclass=mymeta):

'''注釋

'''school='音乃木阪學院'

def __init__(self,name):

self.name=name

def score(self):

print('分數是100')

控制類的呼叫過程,實際上是在控制物件的產生

我們在使用__call__的時候,如果採用物件加()的話,就會呼叫類裡__call__方法

那麼如果我們採用類加()的時候呢?很明顯我們會呼叫元類裡的__call__方法

我們可以因此而不改變類內的東西,只用元類來使該類裡的屬性隱藏

class mymeta(type):

def __call__(self, *args, **kwargs):

obj=object.__new__(self)

# self.__init__(obj,*args, **kwargs) # 也可以用

obj.__init__(*args, **kwargs)

# print(obj.__dict__)

obj.__dict__=

# print(obj.__dict__)

return obj

class person(object, metaclass=mymeta):

school = 'oldboy'

def __init__(self, name):

self.name = name

def score(self):

print('分數是100')

p = person(name='nick')

print(p.__dict__)

# print(p.name) # 會報錯,因為已經被隱藏

類的屬性查詢順序:先從類本身中找--->mro繼承關係去父類中找---->去自己定義的元類中找--->type中--->報錯

物件的屬性查詢順序:先從物件自身找--->類中找--->mro繼承關係去父類中找--->報錯

class mymeta(type):

n=444

def __call__(self, *args, **kwargs): #self=obj=self.__new__(self)

# print(self.__new__ is object.__new__) #true

obj.__init__(*args, **kwargs)

return obj

class bar(object):

# n=333

pass

# def __new__(cls, *args, **kwargs):

# print('bar.__new__')

class foo(bar):

# n=222

pass

# def __new__(cls, *args, **kwargs):

# print('foo.__new__')

class oldboyteacher(foo,metaclass=mymeta):

# n=111

school='oldboy'

def __init__(self,name,age):

self.name=name

self.age=age

def say(self):

print('%s says welcome to the oldboy to learn python' %self.name)

AOP及其原理

aop 動態 能在程式執行期間動態的將某段 片段切入到指定的方法指定位置進行執行的程式設計方式 匯入aop模組,spring aop spring aspects 定義乙個業務邏輯類 mathcalculator 在業務邏輯執行的時候將日誌進行列印 方法之前 方法執行結束 包括方法出現異常等等 定義...

類 友元函式 友元類

友元函式不是當前類的成員函式,但它可以訪問該類所有的成員,包括私有成員 保護成員和公有成員。在類中宣告友元函式時,需在其函式名前加上關鍵字 friend。友元函式既可以是非成員函式,也可以是另乙個類的成員函式。class date date date int y,int m,int d void s...

動態載入類的原理 元資料的使用

在使用.net建立的程式或元件時,元資料 metadata 和 code 都儲存於 自成一體 的單元中,這個單元稱為裝配件。我們可以在程式執行期間訪問這些資訊。在system.reflection中有這樣乙個class assembly,我們可以通過它來載入乙個裝配件。方法如下 assembly a...