一、屬性是什么
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)賦值或讀取的時候,可以做有效性判斷