一、屬性是什么
1. 基本概念
字段:類變量和實(shí)例變量
屬性:對(duì)普通方法修飾后實(shí)現(xiàn)特定的功能
在實(shí)例方法前添加裝飾器@property,后面調(diào)用這個(gè)實(shí)例方法是可直接通過對(duì)象.方法來調(diào)用,可以省略括號(hào);
class Calulator:
pi = 3.1415926
def __init__(self,radius):
self.radius = radius
# 求圓的周長(zhǎng)
@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("圓的周長(zhǎng)",this.perimeter)
print("圓的面積",this.area)
2. 為什么需要屬性
訪問屬性時(shí)可以制造出和訪問字段完全相同的假象;
對(duì)字段值的保護(hù)
二、私有字段
在屬性前加兩個(gè)下劃線,這個(gè)屬性就不允許在類以外的地方訪問
self.__gender = gender # 實(shí)例變量 --- 私有字段
私有字段只能在類的內(nèi)部進(jìn)行訪問和調(diào)用,在類的外面無法訪問。
class Person:
__count = 0 # 類變量 ---- 字段
def __init__(self,name,age,gender=""):
self.name = name # 實(shí)例變量 --- 公共字段
self.age = age
self.__gender = gender # 實(shí)例變量 -- 私有字段
# 每實(shí)例化一次,count+1
Person.__count += 1
@classmethod
def get_count(cls):
print("當(dāng)前實(shí)例化的次數(shù)",str(cls.__count))
def get_gender(self):
print("我的性別為:",self.__gender)
if __name__ == '__main__':
alice = Person("alice", "12", "女")
bob = Person("bob", "22", "男")
# 可以訪問的字段:類、實(shí)例
Person.get_count()
print(alice.name)
# 間接訪問
alice.get_gender()
把私有字段成員變量在類中打包成成員方法,就可以在類外間接訪問;同理,私有字段類變量打包在類中打包成類方法,也可以在類外間接訪問。
三、屬性的基本使用
我們還是通過前面計(jì)算圓的周長(zhǎng)和面積的類來舉例:
class Calulator:
pi = 3.1415926 # 類變量
def __init__(self,radius):
self.radius = radius # 實(shí)例變量
# 求圓的周長(zhǎng)
@property
def perimeter(self):
return 2 * Calulator.pi * self.radius
# 求圓的面積
@property
def area(self):
return Calulator.pi * self.radius * self.radius
pi的值是不允許修改的,我們?nèi)绻麤]有對(duì)pi的值進(jìn)行私有化,隨便一個(gè)方法都可以改變pi的值。
對(duì)于客觀存在的值,不允許外界修改的,我們應(yīng)該將其設(shè)為私有變量。用戶再調(diào)用的過程中是不可以修改的,但是可以寫成接口,用戶可以查看其值。
@classmethod
def get_pi(cls):
return Calulator.__pi
除了pi,我把把半徑設(shè)為私有字段,在構(gòu)造函數(shù)中不再傳入半徑的值,通過成員方法設(shè)置半徑,并且通過屬性給私有字段半徑賦值。
class Calulator:
__pi = 3.1415926 # 類變量
def __init__(self):
self.__radius = 0 # 實(shí)例變量
# 通過屬性獲取半徑的值,構(gòu)造函數(shù)中不用傳入半徑的值
@property
def radius(self):
return self.__radius
# 賦值給半徑
@radius.setter
def radius(self,value):
if not str(value).isdigit():
raise ValueError("半徑必須要符合要求:必須要是正整數(shù)")
if value > 100:
raise ValueError("半徑的值必須要在0-100之間")
else:
self.__radius = value
# 求圓的周長(zhǎng)
@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)
# 打印周長(zhǎng)和面積
print("周長(zhǎng)",this.perimeter)
print("面積",this.area)
注意:使用屬性給私有字段賦值時(shí):函數(shù)名要與使用了屬性裝飾器的函數(shù)名一致,并且裝飾器要寫成
函數(shù)名.setter
這樣做的好處:
(1)可以控制字段:設(shè)置可讀、可寫
(2)賦值或讀取的時(shí)候,可以做有效性判斷