Python 入門 19 —— 類的屬性、 property()

Python 中有三個專門用於裝飾類的方法的內置裝飾器:property()、classmethod()、staticmethod()。因爲這三個裝飾器是Python的內置的,所以,其內部的代碼是不可見,我們只能瞭解它們有什麼作用,被它們裝飾後的類的方法有什麼特殊之處。

一、類的屬性

@ property 裝飾過的類的方法,被稱爲類的屬性。方法變成屬性之後,最大的區別就是在引用時,不可以再傳遞參數,甚至連小括號也不能要了。例如:

class c01:
    @property
    def p01(self): return 100

obj01 = c01()
print(obj01.p01)    # 100
print(obj01.p01())    # TypeError: 'int' object is not callable

使用屬性機制主要是爲了加強對對象的數據成員的保護。

對象數據成員如果是公開的和保護的,那麼就可以隨意地訪問、修改和刪除。如果是私有的,那麼就根本無法訪問。這兩種情況都比較極端:要麼隨意,要麼不可見。那能不能做到既可以訪問,又對修改和刪除進行一定的檢查和限制呢?能,屬性機制就是爲此而生。例如:

class c02:
    def __init__(self,x=100):self.__v= x

    @ property
    def p01(self): return self.__v

obj02=c02()
print(obj02.p01)    # 通過屬性可以訪問私有成員:100
print(obj02.__v)    # 不能直接訪問私有成員:AttributeError: 'c02' object has no attribute '__v'

obj02.p01=200    # AttributeError: can't set attribute
del obj02.p01    # AttributeError: can't delete attribute

實際上,屬性主要就是用於間接地訪問和操作對象的私有數據成員。缺省情況下,屬性既不能被修改,也不能被刪除。不過,通過 property() 函數可以設置訪問、修改、刪除屬性時的魔法函數。

二、property() 函數

通過 property() 函數既可以定義一個屬性,同時還可以設置在訪問、修改、刪除這個屬性時的魔法函數。

屬性名 = property(訪問屬性時的魔法函數名, 修改屬性時的魔法函數名, 刪除屬性時的魔法函數名)

例如:

class c03:
    def __p01get(self):print('Get p01')
    def __p01set(self,x=1):print('Set p01')
    def __p01del(self):print('del p01')
    p01=property(__p01get,__p01set,__p01del)    # 定義屬性 p01,同時設置操作它時的魔法函數

    def __p02get(self):print('Get p02')
    def __p02set(self,x=1):print('Set p02')
    def __p02del(self):print('del p02')
    p02=property(__p02get,__p02set,__p02del)    # 定義屬性 p02,同時設置操作它時的魔法函數

obj03=c03()

obj03.p01    # 訪問屬性時系統自動調用 __p01get(): Get p01
obj03.p01=200    # 修改屬性時系統自動調用 __p01set(): Set p01
del obj03.p01    # 刪除屬性時系統自動調用 __p01del(): del p01

obj03.p02    # Get p02
obj03.p02=200    # Set p02
del obj03.p02    # del p02

三、通過屬性操作私有成員

class c04:
    def __init__(self,x,y):self.__v1= x;self.__v2= y;

    def __p01get(self):return self.__v1

    def __p01set(self,x):
        if x>=10: self.__v1=x; print('Set p01 OK:',self.__v1)
        else: print('Set NO')

    def __p01del(self):del self.__v1; print('p01 Del OK')
    p01=property(__p01get,__p01set,__p01del)    # 通過 p01 可操作私有數據成員 __v1

    def __p02get(self):return self.__v2

    def __p02set(self,x):
        if x<10:self.__v2=x; print('Set p02 OK:',self.__v2)
        else: print('Set NO')

    def __p02del(self): print('p02 Can not Del')
    p02=property(__p02get,__p02set,__p02del)    # 通過 p02 可操作私有數據成員 __v2

obj04=c04(66,88)

print(obj04.p01)   # 66
obj04.p01=5   # 不符合條件不允許修改:Set NO
obj04.p01=15   # 符合條件才允許修改:Set p01 OK: 15
del obj04.p01   # 實際刪除的是私有成員:p01 Del OK

print(obj04.p02)   # 88
obj04.p02=5   # Set p02 OK: 5
obj04.p02=15   # Set NO
del obj04.p02   # 不允許刪除私有成員:p02 Can not Del
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章