特性(property)
一.定義
property是一種特殊的屬性,訪問它時會執行一段功能(函數)然后返回值。
將一個類的函數定義成特性以后,對象再去使用的時候obj.name,根本無法察覺自己的name是執行了一個函數然后計算出來的,這種特性的使用方式遵循了統一訪問的原則
?
1 import math 2 class Circle: 3 def __init__(self,radius): #圓的半徑radius 4 self.radius=radius 5 6 @property #area=property(area) 7 def area(self): 8 return math.pi * self.radius**2 #計算面積 9 10 @property 11 def perimeter(self): 12 return 2*math.pi*self.radius #計算周長 13 14 c=Circle(10) 15 #print(c.area()) 正常這么寫 16 #print(c.perimeter()) 17 print(c.radius) 18 print(c.area) #可以向訪問數據屬性一樣去訪問area,會觸發一個函數的執行,動態計算出一個值 19 print(c.perimeter) #同上 20 ''' 21 輸出結果: 22 10 23 314.1592653589793 24 62.83185307179586 25 '''c.radius=10
c.radius=12
直接計算c.area c.perimeter
好處:
1.將函數偽裝成數據屬性,把數據邏輯偽裝起來。
2.讓身高,體重不斷變的定義函數只用輸入改變的體重,身高值得到BMI值。
注意:此時的特性arear和perimeter不能被賦值
c.area=3 #為特性area賦值 ''' 拋出異常: AttributeError: can't set attribute '''?
ps:面向對象的封裝有三種方式:
【public】
這種其實就是不封裝,是對外公開的
【protected】
這種封裝方式對外不公開,但對朋友(friend)或者子類(形象的說法是“兒子”,但我不知道為什么大家 不說“女兒”,就像“parent”本來是“父母”的意思,但中文都是叫“父類”)公開
【private】
這種封裝對誰都不公開
python并沒有在語法上把它們三個內建到自己的class機制中,在C++里一般會將所有的所有的數據都設置為私有的,然后提供set和get方法(接口)去設置和獲取,在python中通過property方法可以實現
?
1.通過接口訪問
1 class People: 2 def __init__(self,name): 3 self.__Name=name 4 def tell_name(self): #正常的話通過設定接口訪問 5 return self.__Name 6 7 p1=People('cobila') 8 #print(p1._People__Name) 只能訪問這個 9 print(p1.tell_name())2.通過property訪問
1 class People: 2 def __init__(self,name): 3 self.__Name=name #self.__Name 4 @property 5 def name(self): 6 return self.__Name 7 8 p1=People('cobila') 9 #print(p1._People__Name) 只能訪問這個 10 print(p1.name) #讓外面以為訪問的name,其實是self.__Name###不能做p1.name='alex'的賦值操作,ok
?
設置屬性setter
被property修飾的屬性會優于對象的屬性被使用
而被propery裝飾的屬性,如sex,分為三種:
1.property
2.sex.setter
3.sex.deleter
1 class People: 2 def __init__(self,name,sex): 3 self.__Name=name 4 self.__sex=sex 5 @property 6 def sex(self): #2.回到定義 7 return self.__sex #3.取到真實值 8 @sex.setter 9 def sex(self,value): 10 print(self,value) 11 self.__sex=value #1.設置屬性 12 13 p1=People('cobila','male') 14 print(p1.sex) 15 p1.sex='female' 16 print(p1.sex) 17 18 male 19 <__main__.People object at 0x0000000000B618D0> female 20 female?
設定類型限制(Python沒有類型限制,只能自己加)
1 class People: 2 def __init__(self,name,sex): 3 self.__Name=name 4 self.__sex=sex ##初始化操作的,不受下面偽裝的property--setter影響(初始化 p1=People( 'cobila',1234) )也ok的) 但是修改這個再次賦值就會報錯了 5 @property 6 def sex(self): #2.回到定義 7 return self.__sex #3.取到真實值 8 @sex.setter 9 def sex(self,value): 10 #print(self,value) 11 if not isinstance(value,str): 12 raise TypeError('性別必須是字符串類型') 13 self.__sex=value #1.設置屬性 14 15 p1=People('cobila','male') 16 p1.sex='female' 17 print(p1.sex) 18 p1.sex=123123 19 20 21 raise TypeError('性別必須是字符串類型') 22 TypeError: 性別必須是字符串類型刪除
1 class People: 2 def __init__(self,name,sex): 3 self.name=name 4 self.__sex=sex 5 #self.sex=sex 6 @property 7 def sex(self): 8 return self.__sex 9 @sex.setter 10 def sex(self,value): 11 #print(self,value) 12 if not isinstance(value,str): 13 raise TypeError('性別必須是字符串類型') 14 self.__sex=value 15 @sex.deleter 16 def sex(self): 17 del self.__sex 18 19 # p1=People('cobila','male') 20 # p1.sex='female' 21 22 p1=People('cobila','male') 23 del p1.sex #相當于del self.__sex 24 print(p1.sex)?
?
二.靜態方法和類方法
1.靜態方法
類的工具包,專門給類用的
?通常情況下,在類中定義的所有函數(注意了,這里說的就是所有,跟self啥的沒關系,self也只是一個再普通不過的參數而已)都是對象的綁定方法,對象在調用綁定方法時會自動將自己作為參數傳遞給方法的第一個參數。除此之外還有兩種常見的方法:靜態方法和類方法,二者是為類量身定制的,但是實例非要使用,也不會報錯,后續將介紹。
?
?
基于之前所學裝飾器的知識,@staticmethod 等同于spam=staticmethod(spam),于是
class Foo:@staticmethod #裝飾器def spam(x,y,z):print(x,y,z)使用演示
print(type(Foo.spam)) #類型本質就是函數 Foo.spam(1,2,3) #調用函數應該有幾個參數就傳幾個參數f1=Foo() f1.spam(3,3,3) #實例也可以使用,但通常靜態方法都是給類用的,實例在使用時喪失了自動傳值的機制''' <class 'function'> 1 2 3 3 3 3 '''?
?
?
?
?
1 import time 2 class Date: 3 def __init__(self,year,month,day): 4 self.year=year 5 self.month=month 6 self.day=day 7 @staticmethod 8 def now(): #用Date.now()的形式去產生實例,該實例用的是當前時間 9 t=time.localtime() #獲取結構化的時間格式 10 return Date(t.tm_year,t.tm_mon,t.tm_mday) #新建實例并且返回 11 @staticmethod 12 def tomorrow():#用Date.tomorrow()的形式去產生實例,該實例用的是明天的時間 13 t=time.localtime(time.time()+86400) 14 return Date(t.tm_year,t.tm_mon,t.tm_mday) 15 16 a=Date('2019',11,27) #自己定義時間 17 b=Date.now() #采用當前時間 調類下的now 18 c=Date.tomorrow() #采用明天的時間 19 20 print(a.year,a.month,a.day) 21 print(b.year,b.month,b.day) 22 print(c.year,c.month,c.day) 23 24 25 2019 11 27 26 2017 4 21 27 2017 4 22但凡是定義在類的內部,并且沒有被任何裝飾器修飾過的方法,都是綁定方法,有自動傳值功能。
1 d1=Date(1212,22,22) 2 print(d1.now) 3 print(Date.now) 4 #
#但凡定義在類的內部,并且被staticmethod裝飾器修飾過的方法方法,都是解除綁定的方法,實際上就是函數,沒有自動傳值的功能了。 5 d_n1=Date.now() 6 d_n2=d1.now() 7 8 9 10 11 <function Date.now at 0x0000000000D3E2F0> 12 <function Date.now at 0x0000000000D3E2F0>
之前是類調的函數屬性,對象調的函數方法
加上裝飾器后,解除綁定,都是函數屬性
?
2.類方法
?
?
1 class Foo: 2 def bar(self): 3 pass 4 @classmethod #把一個方法綁定給類,自動把對象本身當成一個參數傳進去: 類.綁定到類的方法(),會把類本身當成第一個參數,自動傳給綁定到類的方法 5 def test(cls,x): 6 print(cls,x) #拿掉一個類的內存地址后,就可以實例化或者引用類的屬性 7 print(Foo.bar) #綁定給對象 8 print(Foo.test) #綁定給類 9 f=Foo() 10 print(f.bar) #綁定給foo下的對象f 11 12 13 14 <function Foo.bar at 0x00000000006BE268> 15 <bound method Foo.test of <class '__main__.Foo'>> 16 <bound method Foo.bar of <__main__.Foo object at 0x00000000006C1908>>?
?__str__(self)
__str__定義在類內部必須返回的字符串類型,什么時候回觸發它的執行呢?打印由這個類產生的對象時,會觸發執行 1 class People: 2 def __init__(self,name,age): 3 self.name=name 4 self.age=age 5 def __str__(self): 6 return '<name: %s,age:%s>' %(self.name,self.age) 7 8 p1=People('egon',18) 9 print(p1) 10 11 12 13 <name: egon,age:18>
?
?
1 import time 2 class Date: 3 def __init__(self,year,month,day): 4 self.year=year 5 self.month=month 6 self.day=day 7 @classmethod 8 def now(cls): #用Date.now()的形式去產生實例,該實例用的是當前時間 9 print(cls) 10 t=time.localtime() #獲取結構化的時間格式 11 obj=cls(t.tm_year,t.tm_mon,t.tm_mday) #新建實例并且返回 12 return obj 13 @classmethod 14 def tomorrow(cls):#用Date.tomorrow()的形式去產生實例,該實例用的是明天的時間 15 16 t=time.localtime(time.time()+86400) 17 return cls(t.tm_year,t.tm_mon,t.tm_mday) 18 19 class EuroDate(Date): 20 def __str__(self): 21 return '年:%s,月:%s,日:%s' %(self.year,self.month,self.day) 22 23 e1=EuroDate.now() 24 print(e1) 25 26 27 28 <class '__main__.EuroDate'> 29 年:2017,月:4,日:21?
轉載于:https://www.cnblogs.com/jiangshitong/p/6745212.html
總結
以上是生活随笔為你收集整理的特性(property)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Swift的控制转移语句-- fallt
- 下一篇: 使用 C# 开发智能手机软件:推箱子(十