Python中的屬性與私有字段

一、屬性是什么

1. 基本概念

字段:類變量和實例變量
屬性:對普通方法修飾后實現特定的功能

在實例方法前添加裝飾器@property,后面調用這個實例方法是可直接通過對象.方法來調用,可以省略括號;

class Calulator:
    pi = 3.1415926
    def __init__(self,radius):
        self.radius = radius

    # 求圓的周長
    @property
    def perimeter(self):
        return 2 * Calulator.pi * self.radius

    # 求圓的面積
    @property
    def area(self):
        return Calulator.pi * self.radius * self.radius

if __name__ == '__main__':
    this = Calulator(10)
    print("圓的周長",this.perimeter)
    print("圓的面積",this.area)
2. 為什么需要屬性

訪問屬性時可以制造出和訪問字段完全相同的假象;
對字段值的保護

二、私有字段

在屬性前加兩個下劃線,這個屬性就不允許在類以外的地方訪問

self.__gender = gender  # 實例變量 --- 私有字段 

私有字段只能在類的內部進行訪問和調用,在類的外面無法訪問。

class Person:

    __count = 0 # 類變量 ---- 字段
    def __init__(self,name,age,gender=""):
        self.name = name    # 實例變量  --- 公共字段
        self.age = age
        self.__gender = gender  # 實例變量 -- 私有字段

        # 每實例化一次,count+1
        Person.__count += 1

    @classmethod
    def get_count(cls):
        print("當前實例化的次數",str(cls.__count))

    def get_gender(self):
        print("我的性別為:",self.__gender)

if __name__ == '__main__':
    alice = Person("alice", "12", "女")
    bob = Person("bob", "22", "男")
    # 可以訪問的字段:類、實例
    Person.get_count()
    print(alice.name)
    # 間接訪問
    alice.get_gender()

把私有字段成員變量在類中打包成成員方法,就可以在類外間接訪問;同理,私有字段類變量打包在類中打包成類方法,也可以在類外間接訪問。

三、屬性的基本使用

我們還是通過前面計算圓的周長和面積的類來舉例:

class Calulator:
    pi = 3.1415926  # 類變量
    def __init__(self,radius):
        self.radius = radius    # 實例變量

    # 求圓的周長
    @property
    def perimeter(self):
        return 2 * Calulator.pi * self.radius

    # 求圓的面積
    @property
    def area(self):
        return Calulator.pi * self.radius * self.radius

pi的值是不允許修改的,我們如果沒有對pi的值進行私有化,隨便一個方法都可以改變pi的值。
對于客觀存在的值,不允許外界修改的,我們應該將其設為私有變量。用戶再調用的過程中是不可以修改的,但是可以寫成接口,用戶可以查看其值。

@classmethod
def get_pi(cls):
    return Calulator.__pi

除了pi,我把把半徑設為私有字段,在構造函數中不再傳入半徑的值,通過成員方法設置半徑,并且通過屬性給私有字段半徑賦值。

class Calulator:
    __pi = 3.1415926  # 類變量
    def __init__(self):
        self.__radius = 0    # 實例變量

    # 通過屬性獲取半徑的值,構造函數中不用傳入半徑的值
    @property
    def radius(self):
        return self.__radius

    # 賦值給半徑
    @radius.setter
    def radius(self,value):
        if not str(value).isdigit():
            raise ValueError("半徑必須要符合要求:必須要是正整數")
        if value > 100:
            raise ValueError("半徑的值必須要在0-100之間")
        else:
            self.__radius = value

    # 求圓的周長
    @property
    def perimeter(self):
        return 2 * Calulator.__pi * self.radius

    # 求圓的面積
    @property
    def area(self):
        return Calulator.__pi * self.radius * self.radius

    # 給用戶查看pi值的接口
    @classmethod
    def get_pi(cls):
        return Calulator.__pi

if __name__ == '__main__':

    this = Calulator()
    # 獲取半徑值
    print(this.radius)
    # 賦值給半徑
    this.radius = 10  # 這種屬性賦值的方式很特殊!
    # 獲取半徑值
    print(this.radius)
    # 打印周長和面積
    print("周長",this.perimeter)
    print("面積",this.area)

注意:使用屬性給私有字段賦值時:函數名要與使用了屬性裝飾器的函數名一致,并且裝飾器要寫成函數名.setter

這樣做的好處:
(1)可以控制字段:設置可讀、可寫
(2)賦值或讀取的時候,可以做有效性判斷

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。