1. 程式人生 > 實用技巧 >🍖類的 property 特性

🍖類的 property 特性

一.特性 property

1.什麼是 property 特性

property 裝飾器可以用於裝飾類裡面的方法, 讓其偽裝成一個數據屬性, 也就是在呼叫的時候可以不用加括號

2.定義一個 property 特性

class Person:
    def run(self):
        print("小王在跑")

    @property  # 定義property屬性
    def speak(self):
        print("李白在說話")

P1= Person()

P1.run()  # 小王在跑
P1.speak  # 李白在說話 (呼叫property屬性)

3.為什麼要有 property 特性

  • 將類的一個函式(方法)定義成 property 特性之後, 不加括號的去使用 [物件].[方法] 的時候, 我們無法察覺自己是執行了一個函式(方法), 這種特性的使用方式遵循了統一訪問的原則

4.property 屬性的定義和呼叫的注意點

  • 定義時 : 在例項方法的上方新增 @property 裝飾器, 並且僅有一個 self引數
  • 呼叫時 : 無需加括號

二.property 屬性的使用兩種方法

1.第一種 : 使用 property( ) 函式 (古老用法, 瞭解即可)

class Person:
    def __init__(self):
        self.__name= None

    #這是setter方法
    def set_name(self,name):
        print("設定了名字")
        self.__name=name

    #這是getter方法
    def get_name(self):
        print("獲取了名字")
        return self.__name

    # 這是deleter方法
    def del_name(self):
        print("刪除了名字")
        del self.__name

    name=property(get_name,set_name,del_name) # 這裡存放的是"name"的所有操作

P1 = Person()

P1.name = 'Shawn'  # 設定了名字 (直接賦值,等同於 P1.set_name('Shawn'))
n = P1.name        # 獲取了名字 (直接獲取資料 ,等同於 P1.get_name())
print(n)           # Shawn
del P1.name        # 刪除了名字 (刪除屬性)
print(P1.name)     # 屬性被刪除了, 再次檢視報錯 : "AttributeError" 沒有該屬性

2.第二種 : 使用 @property 裝飾器 (新方法)

  • 第二種方法 getter 必須寫在 setter 和 deleter 的前面 (說是這麼說, 但是實驗了一下可以寫在後面)
  • @property 裝飾器必須寫在 三者最前面, 並且三者都必須使用被@property修飾的同一個函式名, 否則報錯
class Person:
    def __init__(self):
        self.__name= None

    @property 
    def name(self):       # 獲取
        print("設定了名字")
        return self.__name

    @name.setter
    def name(self,name): # 設定
        print("設定名字成功")
        self.__name=name

    @name.deleter        # 刪除
    def name(self):
        print("刪除了名字")
        del self.__name

    @name.getter         # 獲取
    def name(self):
        print("查看了名字並+'哈哈'")
        return self.__name + "哈哈"

P1 = Person()
P1.name = "shawn"  # 設定名字成功
n = P1.name        # 查看了名字並+'哈哈'
print(n)           # shawn哈哈

由上面的例子實驗, 我們可以發現一個問題: @property 下修飾的功能其實是與 @name.getter 的功能重複的, 於是我們可以省略 @name.getter 不用寫, 其實就是 @property 替代了 @name.getter

3.注意點

  • 經典類中的屬性只有一種訪問方式,其對應被 @property 修飾的方法
  • 新式類中的屬性有三種訪問方式,並分別對應了三個被 @property@方法名.setter@方法名.deleter 修飾的方法 (獲取、修改、刪除)

4.總結

  • 定義property屬性共有兩種方式,分別是裝飾器類屬性,而裝飾器方式針對經典類和新式類又有所不同。
  • 通過使用property屬性,能夠簡化呼叫者在獲取資料的流程, 就是重新實現一個屬性的設定和讀取方法

三.property 特性的應用

1.property 與類的封裝組合使用

其實上面的示例就是"property"特性與類的封裝的組合使用

2.練習 : 計算圓的周長與面積

import math

class Circle:
    def __init__(self,radius):
        self.__radius = radius

    @property
    def area(self):
        return f"面積{math.pi * self.__radius ** 2}"

    @property
    def perimeter(self):
        return f"周長{2 * math.pi * self.__radius}"

C1 = Circle(10)
print(C1.area)      # 面積:314.1592653589793
print(C1.perimeter) # 周長:62.83185307179586

3.練習 : 計算BMI指數 (體質指數)

  • 利用身高與體重的比例來衡量一個人是否過瘦或過肥
  • 公式 : BMI = 體重(kg) / (身高(m) ** 2)
  • 範圍 : (過輕:低於18.5), (正常:18.5-23.9), (過重:24-27), (肥胖:28-32), (非常肥胖, 高於32)
class Person:
    def __init__(self,weight,hight):
        self.__weight = weight
        self.__hight = hight

    @property
    def BMI(self):
        return f"BMI值 : {self.__weight / (self.__hight ** 2)}"

P1 = Person(56,1.73)
print(P1.BMI)  # BMI值 : 18.710949246550168