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)