1. 程式人生 > >python之property,classmethod,staticmethod

python之property,classmethod,staticmethod

property屬性

什麼是特性property

property是一種特殊的屬性,訪問它時會執行一段功能(函式)然後返回值,就是以前我們要呼叫方法,形式是物件.方法名(),有了這個屬性就可以直接以呼叫屬性的方式進行呼叫

property裝飾的bmi仍然是一個方法 存在Person.dict
物件的.__dict__中不會儲存這個屬性

在一個類載入的過程中,會先載入這個中的名字,包括被property裝飾的

在例項化物件的時候,python直譯器會先到類的空間裡看看有沒有這個被裝飾的屬性,
如果有就不能再在自己物件的空間中建立這個屬性了
例一:人體的BMI指數:

class Person():
    def __init__(self, name, weight, height):
        self.name = name
        self.__height = height
        self.__weight = weight
    @property
    def cal_BIM(self):
        return self.__weight/self.__height ** 2
p = Person('dear', 65, 1.73)
print(p.cal_BIM)

例二:圓的面積

import math
class Circle:
    def __init__(self, r):
        self.r = r
 
    @property
    def area(self):
        return self.r **2 * math.pi
 
    @property
    def perimeter(self):
        return self.r *2 * math.pi
c=Circle(10)
print(c.r)
print(c.area) #可以向訪問資料屬性一樣去訪問area,會觸發一個函式的執行,動態計算出一個值
print(c.perimeter) #同上

#注意:此時的特性area和perimeter不能被賦值
c.area=3 #為特性area賦值
‘’’
丟擲異常:
AttributeError: can’t set attribute
‘’’
為什麼要用property

將一個類的函式定義成特性以後,物件再去使用的時候obj.name,根本無法察覺自己的name是執行了一個函式然後計算出來的,這種特性的使用方式遵循了統一訪問的原則

ps:面向物件的封裝有三種方式:
【public】
這種其實就是不封裝,是對外公開的
【protected】
這種封裝方式對外不公開,但對朋友(friend)或者子類(形象的說法是“兒子”,但我不知道為什麼大家 不說“女兒”,就像“parent”本來是“父母”的意思,但中文都是叫“父類”)公開
【private】
這種封裝對誰都不公開
但是Python中只有兩種,【public】,【private】

python並沒有在語法上把它們三個內建到自己的class機制中,在C++裡一般會將所有的所有的資料都設定為私有的,然後提供set和get方法(介面)去設定和獲取,在python中通過property方法可以實現。
一個靜態屬性property本質就是實現了get,set,delete三種方法

class Person:
    def __init__(self, name):
        self.__name = name  #私有屬性
    @property
    def name(self):
        return self.__name
 
    # 方法偽裝成的屬性的修改
    @name.setter
    def name(self, new_name):
        if type(new_name) is str:
            self.__name = new_name
        else:
            print('您提供的姓名資料型別不合法')
 
    # 方法偽裝成的屬性的刪除
    @name.deleter
    def name(self):
        del self.__name
p = Person('happy')
print(p.name)      #執行def name(self):
p.name = 'like'   #修改名字,執行def name(self, new_name):
del p.name   #執行了被@name.deleter裝飾的函式

具體例項用法:

# 商品的 折扣
# 有一個商品 : 原價 折扣
# 當我要檢視價格的時候 我想看折後價
class Goods:
    def __init__(self, name, origin_price, discount):
        self.name = name
        self.__price = origin_price
        self.__discount = discount
 
    @property
    def price(self):
        return self.__price * self.__discount
    @price.setter
    def price(self, new_price):
        if type(new_price) is int or type(new_price) is float:
            self.__price = new_price
 
 
apple = Goods('apple',5,0.8)
print(apple.price)
# # 修改蘋果的原價
apple.price = 8
print(apple.price)

作用:
將一些需要隨著一部分屬性的變化而變化的值的計算過程 從方法 偽裝成屬性

將私有的屬性保護起來,讓修改的部分增加一些約束,來提高程式的穩定性和資料的安全性

classmethod

# 店慶 全場八折
class Goods:
    __discount = 0.8
    def __init__(self,name,origin_price):
        self.name = name
        self.__price = origin_price
 
    @property
    def price(self):
        return self.__price * Goods.__discount
    @classmethod
    def change_discount(cls, new_discount):     # 類方法可以直接被類呼叫 不需要預設傳物件引數 只需要傳一個類引數就可以了
        cls.__discount = new_discount
 
apple = Goods('apple',5)
banana = Goods('banana',8)
print(apple.price)
print(banana.price)
#折扣變了
Goods.change_discount(1)       # 不依賴物件的方法 就應該定義成類方法 類方法可以任意的操作類中的靜態變數
print(apple.price)
print(banana.price)

staticmethod

當一個方法要使用物件的屬性時 就是用普通的方法
當一個方法要使用類中的靜態屬性時 就是用類方法
當一個方法要既不使用物件的屬性也不使用類中的靜態屬性時,就可以使用staticmethod靜態方法

class Student:
    def __init__(self,name):pass
 
    @staticmethod
    def login( a ):                   # login就是一個類中的靜態方法 靜態方法沒有預設引數 就當成普通的函式使用即可
        user = input('user :')
        if user == 'haha':
            print('success')
        else:
            print('faild')
Student.login(1)