1. 程式人生 > 其它 >面向物件微講解(四)

面向物件微講解(四)

面向物件微講解(四)

面向物件雙下方法

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小白陸祿緋,歡迎各位大佬的指點!!!