python類的內置方法

python類的內置方法

一、new、init

__new__方法是真正的類構造方法,用於產生實例化對象(空屬性)。重寫__new__方法能夠控制對象的產生過程。
__init__方法是初始化方法,負責對實例化對象進行屬性值初始化,此方法必須返回None,__new__方法必須返回一個對象。重寫__init__方法能夠控制對象的初始化過程。python

# 使用new來處理單例模式

class Student:
    __instance = None

    def __new__(cls, *args, **kwargs):
        if not cls.__instance:
            cls.__instance = object.__new__(cls)
        return cls.__instance

    def sleep(self):
        print('sleeping...')

stu1 = Student()
stu2 = Student()

print(id(stu1), id(stu2))  # 二者輸出相同
print(stu1 is stu2)  # True

我的感受,__new__通常不多用於普通的業務場景,更多的用於元類之中,由於能夠更底層的處理對象的產生過程。而__init__的使用場景更多。mysql

二、str、repr

二者的目的都是爲了顯式的顯示對象的一些必要信息,方便查看和調試。__str__print默認調用,__repr__被控制檯輸出時默認調用。即,使用__str__控制用戶展現,使用__repr__控制調試展現。sql

# 默認全部類繼承object類,object類應該有一個默認的str和repr方法,打印的是對象的來源以及對應的內存地址

class Student:
    def __init__(self, name, age):
        self.name = name
        self.age = age

stu = Student('zlw', 26)
print(stu)  # <__main__.Student object at 0x0000016ED4BABA90>
# 自定義str來控制print的顯示內容,str函數必須return一個字符串對象
# 使用repr = str來偷懶控制檯和print的顯示一致

class Student:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __str__(self):
        return f'{self.__class__}, {self.name}, {self.age}'
    
    __repr__ = __str__

stu = Student('zlw', 26)
print(stu)  # <class '__main__.Student'>, zlw, 26

三、call

__call__方法提供給對象能夠被執行的能力,就像函數那樣,而本質上,函數就是對象,函數就是一個擁有__call__方法的對象。擁有__call__方法的對象,使用callable能夠獲得True的結果,可使用()執行,執行時,能夠傳入參數,也能夠返回值。因此咱們可使用__call__方法來實現實例化對象做爲裝飾器:數據庫

# 檢查一個函數的輸入參數個數, 若是調用此函數時提供的參數個數不符合預約義,則沒法調用。

# 單純函數版本裝飾器
def args_num_require(require_num):
    def outer(func):
        def inner(*args, **kw):
            if len(args) != require_num:
                print('函數參數個數不符合預約義,沒法執行函數')
                return None

            return func(*args, **kw)
        return inner
    return outer

@args_num_require(2)
def show(*args):
    print('show函數成功執行!')

show(1)  # 函數參數個數不符合預約義,沒法執行函數
show(1,2) # show函數成功執行!
show(1,2,3)  # 函數參數個數不符合預約義,沒法執行函數
# 檢查一個函數的輸入參數個數,
# 若是調用此函數時提供的參數個數不符合預約義,則沒法調用。

# 實例對象版本裝飾器
class Checker:
    def __init__(self, require_num):
        self.require_num = require_num

    def __call__(self, func):
        self.func = func

        def inner(*args, **kw):
            if len(args) != self.require_num:
                print('函數參數個數不符合預約義,沒法執行函數')
                return None

            return self.func(*args, **kw)
        return inner

@Checker(2)
def show(*args):
    print('show函數成功執行!')

show(1)  # 函數參數個數不符合預約義,沒法執行函數
show(1,2) # show函數成功執行!
show(1,2,3)  # 函數參數個數不符合預約義,沒法執行函數

四、del

__del__用於當對象的引用計數爲0時自動調用。
__del__通常出如今兩個地方:一、手工使用del減小對象引用計數至0,被垃圾回收處理時調用。二、程序結束時調用。
__del__通常用於須要聲明在對象被刪除前須要處理的資源回收操做app

# 手工調用del 能夠將對象引用計數減一,若是減到0,將會觸發垃圾回收

class Student:

    def __del__(self):
        print('調用對象的del方法,此方法將會回收此對象內存地址')

stu = Student()  # 調用對象的__del__方法回收此對象內存地址

del stu

print('下面還有程序其餘代碼')
class Student:

    def __del__(self):
        print('調用對象的del方法,此方法將會回收此對象內存地址')

stu = Student()  # 程序直接結束,也會調用對象的__del__方法回收地址

五、iter、next

這2個方法用於將一個對象模擬成序列。內置類型如列表、元組均可以被迭代,文件對象也能夠被迭代獲取每一行內容。重寫這兩個方法就能夠實現自定義的迭代對象。函數

# 定義一個指定範圍的天然數類,並能夠提供迭代

class Num:
    def __init__(self, max_num):
        self.max_num = max_num
        self.count = 0
        
    def __iter__(self):
        return self

    def __next__(self):
        if self.count < self.max_num:
            self.count += 1
            return self.count
        else:
            raise StopIteration('已經到達臨界')
        
num = Num(10)
for i in num:
    print(i)  # 循環打印1---10

六、getitem、setitem、delitem

重寫此係列方法能夠模擬對象成列表或者是字典,便可以使用key-value的類型。ui

class StudentManager:
    li = []
    dic = {}

    def add(self, obj):
        self.li.append(obj)
        self.dic[obj.name] = obj

    def __getitem__(self, item):
        if isinstance(item, int):
            # 經過下標獲得對象
            return self.li[item]
        elif isinstance(item, slice):
            # 經過切片獲得一串對象
            start = item.start
            stop = item.stop
            return [student for student in self.li[start:stop]]
        elif isinstance(item, str):
            # 經過名字獲得對象
            return self.dic.get(item, None)
        else:
            # 給定的key類型錯誤
            raise TypeError('你輸入的key類型錯誤!')

class Student:
    manager = StudentManager()

    def __init__(self, name):
        self.name = name

        self.manager.add(self)

    def __str__(self):
        return f'學生: {self.name}'

    __repr__ = __str__


stu1 = Student('小明')
stu2 = Student('大白')
stu3 = Student('小紅')
stu4 = Student('胖虎')

# 當作列表使用
print(Student.manager[0])  # 學生: 小明
print(Student.manager[-1])  # 學生: 胖虎
print(Student.manager[1:3])  # [學生: 大白, 學生: 小紅]

# 當作字典使用
print(Student.manager['胖虎'])  # 學生: 胖虎

七、getattr、setattr、delattr

當使用obj.x = y的時候觸發對象的setattr方法,當del obj.x的時候觸發對象的delattr方法。
當嘗試訪問對象的一個不存在的屬性時 obj.noexist 會觸發getattr方法,getattr方法是屬性查找中優先級最低的。
能夠重寫這3個方法來控制對象屬性的訪問、設置和刪除。
**特別注意:若是定義了getattr,而沒有任何代碼(即只有pass),則全部不存在的屬性值都是None而不會報錯,可使用super().__getattr__()方法來處理**調試

class Student:
    def __getattr__(self, item):
        print('訪問一個不存在的屬性時候觸發')
        return '不存在'

    def __setattr__(self, key, value):
        print('設置一個屬性值的時候觸發')
        # self.key = value  # 這樣會無限循環
        self.__dict__[key] = value

    def __delattr__(self, item):
        print('刪除一個屬性的時候觸發')
        if self.__dict__.get(item, None):
            del self.__dict__[item]

stu = Student()
stu.name = 'zlw'  # 設置一個屬性值的時候觸發
print(stu.noexit)  # 訪問一個不存在的屬性時候觸發 , 返回'不存在'
del stu.name  # 刪除一個屬性的時候觸發

八、getatrribute

這是一個屬性訪問截斷器,即,在你訪問屬性時,這個方法會把你的訪問行爲截斷,並優先執行此方法中的代碼,此方法應該是屬性查找順序中優先級最高的。
屬性查找順序:實例的getattribute-->實例對象字典-->實例所在類字典-->實例所在類的父類(MRO順序)字典-->實例所在類的getattr-->報錯code

class People:
    a = 200

class Student(People):
    a = 100

    def __init__(self, a):
        self.a = a

    def __getattr__(self, item):
        print('沒有找到:', item)

    def __getattribute__(self, item):
        print('屬性訪問截斷器')
        if item == 'a':
            return 1
        return super().__getattribute__(item)

stu = Student(1)
print(stu.a)  # 1

九、enter、exit

這兩個方法的重寫可讓咱們對一個對象使用with方法來處理工做前的準備,以及工做以後的清掃行爲。對象

class MySQL:
    def connect(self):
        print('啓動數據庫鏈接,申請系統資源')

    def execute(self):
        print('執行sql命令,操做數據')

    def finish(self):
        print('數據庫鏈接關閉,清理系統資源')

    def __enter__(self):  # with的時候觸發,並賦給as變量
        self.connect()
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):  # 離開with語句塊時觸發
        self.finish()

with MySQL() as mysql:
    mysql.execute()
    
# 結果:
# 啓動數據庫鏈接,申請系統資源
# 執行sql命令,操做數據
# 數據庫鏈接關閉,清理系統資源

十、get、set、delete、描述符(研究中,待補充)

相關文章
相關標籤/搜索