就是with … as …這種方式的使用原理
class Foo:def __init__(self,name,age):self.name= nameself.age= agedef __enter__(self): #當調用類Foo時就會觸發__enter__方法print('__enter__正在被觸發')return self #將類Foo的屬性作為返回值def __exit__(self,exc_type,exc_val,exc_tb): #self后的三個參數為必要屬性print('執行__exit__')#當整個類執行完畢以后就會觸發exit的運行,#或者執行過程中出現了異常也會觸發exit方法的運行,并停止程序的運行#但若返回一個True就不會停止整個程序的運行,只是停止類的執行,后續代碼可以繼續執行return Truewith Foo('a.txt',18) as f: #只要調用了with Foo...就是觸發__enter__#將一個文件傳入Foo中,因為返回值是self屬性,所以f就代表了selfprint(f.name) #可直接調用,相當于self.name#一個錯誤語句print(djksjsgg)#with ... as ...就是上下文協議管理,打開文件也是這個原理,當文件執行完畢后會自動關閉
with open('a.txt','r',encoding='gbk') as fi:re = fi.read()print(re)print('===============》》》結束')
運行結果:
要知道,在Python中,一切皆對象;所以裝飾器不僅可以修飾函數,還可以修飾類;可以用函數來定義,也可以用類(描述符)來定義
#定義一個裝飾器(本質上就是個修飾函數的函數)
def adorn1(func):print('=========>>>')func.x = 1314 #給函數加一屬性xreturn func@adorn1 #加上裝飾器,相當于test=deco(test),把原函數放進裝飾器處理后返回給原函數
def test():print('test函數運行了')
test() #調用函數
#神奇一幕,一切皆對象,就連函數都可以有屬性字典
print(test.x) #輸出函數的屬性x
print(test.__dict__) #輸出函數的屬性字典print('===========================>>>')#修飾類的裝飾器
def adorn2(obj):print('obj的所屬類是:',obj) #傳入一個類到obj形參,就可以處理類的屬性了obj.x = 520 #增加屬性字典的鍵值對return obj #返回被修飾后的類#在類上用裝飾器,同樣適用
@adorn2
class Foo:pass
f1 = Foo() #實例化
#print(f1) #輸出類的內存地址信息
print(f1.x)
運行結果:
#@property原理,就是一個裝飾器
class Self_property:def __init__(self,func): #獲得屬性并但不處理屬性self.func = func#將Self_property做成一個描述符(一個類修飾另外一個類),以得到返回值def __get__(self,instance,owner): #后兩個的必須參數有print('get被觸發!,instance就是:',instance)res = self.func(instance) #返回func的運行結果,即area的運行結果return resclass Room:def __init__(self,name,width,length):self.name = nameself.width = widthself.length = length#@property#類的裝飾器,相當于area=property(area),效果是使area函數能后執行一遍@Self_propertydef area(self):return self.width * self.length #返回寬*長(面積)print('==============Room的字典==============')
print(Room.__dict__) #加了描述符后Room的屬性里就有了這個描述符print('\n===============實例化結果==============')
r1 = Room('澡堂',5,5) #實例化
print('面積是:',r1.area)
#有了Self_property后,就與property有了一樣的效果,可以直接運行類內部的函數
運行結果:
class Foo:@propertydef TTT(self):print('TTT被運行')@TTT.setter #當設置值的時候會觸發TTT.setter下定義的函數def TTT(self,val):print('set的時候運行setter',val)@TTT.deleter #當刪除值的時候觸發TTT.delete下定義的函數def TTT(self):print('del的時候觸發deleter')f = Foo()
f.TTT #運行TTT函數
f.TTT='我被改了' #將TTT屬性改為值'我被改了'
del f.TTT
運行結果:
就是類的類,是類的模板,是用來控制如何創建類的;
元類的實例就是類,就像類的實例就是對象
class Foo:pass
f1 = Foo() #實例化對象f1
#輸出類型
#print(type(f1)) #f1的類就是Foo
print(type(Foo)) #Foo的類就是type,就是說所有的類都是屬于type類#給元類加self屬性
def __init__(self,name,age):self.name = nameself.age = age
#加其他函數屬性
def test(self):print('這是test函數屬性')#通過元類來定義對象,因為一切皆對象,所以由type定義來的對象就一個類
Foo2 = type('Foo',(object,),{'name':'View','__init__':__init__,'test':test})
#表明定義一個繼承Foo的類,里面有一個鍵值對'name':'View'
print(Foo2)
print('==========Foo2屬性字典==========')
print(Foo2.__dict__)f2 = Foo2('路飛','19') #用新類實例化對象f2
print(f2.name) #輸出f2的數據屬性
f2.test() #運行函數屬性
運行結果:
class MyType(type): #一個繼承type的類def __init_(self,a,b,c): #元類必須有4個參數print('我是元類函數!',self.name)print(a,b,c)def __call__(self,*args,**kwargs): #定義__call__方法obj = object.__new__(self) #新建一個對象來把Foo傳入的參數變為MyType的屬性self.__init__(obj,*args,**kwargs)return obj#MyType來定義類
class Foo(metaclass=MyType): #相當于Mytype('Foo',(object,),{})def __init__(self,name):self.name = name #封裝從MyType傳來的屬性#實例化
f1= Foo('View')
#Foo這個用MyType定義的類不會自動觸發__init__方法,只會觸發__call__方法
print(Foo.__dict__,'\n') #輸出Foo的屬性字典,并補包括'name': 'View'
print(f1.__dict__) #輸出f1的屬性字典
運行結果:
版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。
工作时间:8:00-18:00
客服电话
电子邮件
admin@qq.com
扫码二维码
获取最新动态