面向物件微講解(四)
阿新 • • 發佈:2022-04-11
面向物件微講解(四)
面向物件雙下方法
1.__str__:物件被執行列印(print、前端展示)操作的時候自動觸發,該方法必須返回字串型別的資料,很多時候用來更 加精準的描述物件。 class Student: def __init__(self,name): self.name = name def __str__(self): print('什麼時候列印我') return '這是一個物件%s'%self.name obj = Student('oscar') print(obj) # 當我們執行列印語句的時候,__str__會自動執行
2.__del__:物件被執行(被動、主動)刪除操作之後自己執行。(相當於我們只講過的垃圾回收機制)
class Student:
def __init__(self,name):
self.name = name
def __del__(self):
print('什麼時候列印我')
obj = Student('oscar')
# del obj # 這是主動執行,可以指定執行的地方
print(obj.name) # 先輸出的列印語句,然後自動執行的__del__方法
3.__getattr__:物件查詢不存在的名字的時候自動觸發。 class Student: def __init__(self,name): self.name = name def __getattr__(self, item): print('什麼時候列印我') return '%s不存在'%item obj = Student('oscar') print(obj.name) # 列印oscar,不執行__getattr__方法 print(obj.age) # 執行__getattr__方法
4.__getattribute__:只要物件查詢名字,無論名字是否存在都會執行該方法,如果類中有__getattribute__方法就不會 執行__getattr__方法。 class Student: def __init__(self,name): self.name = name def __getattribute__(self, item): print('無論什麼時候列印我') return item obj = Student('oscar') print(obj.name) # 都會執行列印,不會報錯 print(obj.age) # 都會執行列印,不會報錯
5.__setattr__:在物件執行新增屬性操作的時候觸發。
class Student:
def __setattr__(self, key, value):
print('你添加了鍵值對k:%s v:%s'%(key,value))
obj = Student()
obj.name = 'oscar' # 執行這一句的時候自動執行__setattr__方法
6.__call__:物件被加括號呼叫的時候自動執行。
class Student:
def __init__(self,name):
self.name = name
def __call__(self, *args, **kwargs):
print('什麼時候列印我')
return 123
obj = Student('oscar')
print(obj()) # 物件是不能直接加括號呼叫的,加了__call__方法就可以,返回值後面跟什麼就返回什麼
7.__enter__:物件被執行with語法的時候自動執行,該方法返回什麼as後面的變數名就會得到什麼。
__exit__:物件被執行with語法結束的時候自動執行。
class Student:
def __init__(self,name):
self.name = name
def __enter__(self):
return self
def __exit__(self, exc_type, exc_val, exc_tb):
pass
obj = Student('oscar')
with obj as f:
res = f.name
print(res) # oscar
元類
1.元類簡介
1.元類即原始的類,產生類的類。
2.學習元類的目的:元類能夠控制類的建立,也就意味著我們可以高度定製類的行為。
# print(type(123)) # <class 'int'>
# print(type([123,11,'oscar'])) #<class 'list'>
# print(type('oscar')) # <class 'str'>
'''我們type關鍵字檢視資料型別的時候,會返回資料的型別,
我們會發現前面有一個class,實質資料型別也是一個類,那我們
能不能type一個類,來看看產生類的類是什麼
'''
class Student:
pass
print(type(Student)) # <class 'type'>
class Teacher(Student):
pass
print(type(Teacher)) # <class 'type'>
'''
我們會發現都是type,所以type就是所有類預設的元類
'''
2.產生類的兩種變現形式
1.class關鍵字
class 類名:
類體程式碼
2.type元類
# type(類名,父類,類的名稱空間)
res = type('Student',(),{})
print(res) # <class '__main__.Student'>
3.元類的基本使用
1.元類是不能夠通過繼承的方式直接指定的,需要通過關鍵字'metaclass'引數的形式修改。
# 修改元類的方法,建立類的時候首字母必須大寫,否則就報錯
class Student(type):
def __init__(cls,cls_name,cls_bases,cls_dict):
if not cls_name.istitle():
raise Exception('建立類的時候類名首字母必須大寫!!')
super().__init__(cls_name,cls_bases,cls_dict)
class Teacher(metaclass=Student): # 通過關鍵字'metaclass'引數的形式修改。
name = 'oscar'
# class teacher(metaclass=Student):
# name = 'oscar'
4.元類進階操作
1.我們之前講__call__方法的時候,物件加括號會自動執行產生該物件的類裡面的__call__,並且該方法返回什麼物件加
括號就會得到什麼,那我們就可以推導類加括號會執行元類的裡面的__call__,該方法返回什麼類加括號就會得到什麼。
2.類裡面的__init__和元類的__call__執行的先後順序。
class Student(type):
def __call__(self, *args, **kwargs):
print('我是__call__')
super().__call__(*args, **kwargs)
class Teacher(metaclass=Student):
def __init__(self,name):
print('我是__init__')
self.name = name
obj = Teacher('oscar')
'''
我是__call__
我是__init__
先執性元類的__call__方法,然後在執行類的__init__方法
'''
3.定製物件的產生過程
class Student(type):
def __call__(self, *args, **kwargs):
if args:
raise Exception('必須全部採用關鍵字引數')
super().__call__(*args, **kwargs)
class Teacher(metaclass=Student):
def __init__(self,name):
self.name = name
obj = Teacher(name = 'oscar')
'''
如果你想高度定製類的產生過程:就編寫元類裡面的__init__方法。
如果你想高度定製物件的產生過程:就編寫元類裡面的__call__方法。
'''
5.雙下new方法
__new__用於產生空物件(類)
__init__用於例項化物件(類)
# 並不是所有的地方都可以直接呼叫__new__,該方法過於底層。
1.如果是在元類的__new__裡面可以直接呼叫
class Student(type):
def __call__(cls, *args, **kwargs):
obj = type.__new__(cls,*args,**kwargs)
return obj
2.如果在元類的__call__裡面需要間接呼叫
class Student(type):
def __call__(self, *args, **kwargs):
obj = type.__new__(self) # 建立一個空物件
self.__init__(obj,*args,**kwargs) # 讓物件去初始化
return obj
這裡是IT小白陸祿緋,歡迎各位大佬的指點!!!