在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...