<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
這幾天看《流暢的python》這本書了,在一個範例中又看到了property作為裝飾器在使用,因為很久沒有用這個東西了,對它的一些特性和使用方法等都不是很熟悉,所以又專門在搜了幾篇部落格和在官方檔案中學習了它的相關用法。再者又剛好學到了python中的屬性(attribute),所以剛好這兩者可以兩相對比,也許更好理解!
在python中,屬性其實是(物件的)屬性和(物件的)方法的集合。
一開始我以為就是:屬性就是屬性,方法就是方法,一個是“屬性”,一個是行為,但是在開啟IDE寫了一個測試案例後,我就信服了:
# python中資料的屬性和處理資料的方法統稱為屬性 class Cat: def __init__(self, name): self.name = name def run(self): print('小碎步...') if __name__ == '__main__': tom = Cat('Tom') print(tom.__getattribute__('name')) # 物件的屬性 print(tom.__getattribute__('run')) # 物件的方法
在這裡我定義了一個類,同時在初始化方法中為它新增了一個屬性name,然後定義了一個run方法,之後在main方法裡建立了tom這個範例,使用__getattribute__()方法來獲取它的name屬性和run屬性,果不其然,居然真的都獲取到了!
所以,以後再也不要說屬性只是單純的“屬性”了!
屬性用法很簡單,不管是物件的屬性還是方法,都是用.來獲取或者呼叫。
1.設定或修改物件的屬性
tom.name='Tom' #設定(修改)物件tom的name屬性值為Tom
2.刪除物件的屬性
del tom.name #使用del關鍵字刪除物件的屬性
可以看到,屬性刪除後就不能再獲取了。
3.呼叫物件的方法(屬性)
tom.run() #直接用.呼叫即可
4.物件的方法置None
物件的方法我們無法刪除,但是我們可以將其置為None。
tom.run=None
個人理解:特性就是屬性的特例,因為預先知道某些屬性的一些特定條件,比如取值範圍,型別等等,所以在對這些屬性進行操作的時候,為了在操作前後,保持一些特定條件不變(就是不準越界操作),所以就有了特性來約束它。
來看一下官方檔案給的例子:
官方檔案中提到:一個典型的例子就是託管x(這裡的x是一個類的屬性), 使用方法也特別的直接明瞭:如果 c 為 C 的範例,c.x
將呼叫 getter,c.x = value
將呼叫 setter, del c.x
將呼叫 deleter。就是在對c.x這個屬性進行操作時,可以通過getter,setter,delx來控制它的修改和刪除。
因為它是一個修飾器,所以呼叫方法有兩種:
1.直接使用@符號呼叫
class Dog: def __init__(self): self.__name = None @property def name(self): print('呼叫了get_name方法...') return self.__name @name.setter def name(self, val): print('呼叫了set_name方法...') self.__name = val @name.deleter def name(self): print('呼叫了del_name方法...') del self.__name if __name__ == '__main__': tom = Dog() tom.name = 'Tom' print(tom.name) del tom.name
2.當做一個正常的函數使用
class Cat: def __init__(self): self.__name = None def set_name(self, name): print('呼叫了set_name方法...') self.__name = name def get_name(self): print('呼叫了get_name方法...') return self.__name def del_name(self): print('呼叫了del_name方法...') del self.__name name = property(get_name, set_name, del_name, 'this is a property name.') if __name__ == '__main__': tom = Cat() tom.name = 'Tom' print(tom.name) del tom.name
可以看到兩種方法使用的效果都是一樣的!
重點講一下這個,正是因為有一些特定場景的存在,才會出現property這個特性的,正如之前在《Django企業開發實戰》一書中所說的那樣:若無必要,勿增實體。而python向來以簡潔優雅著稱,因為這些特定場景,所以是有必要增加property這個實體的。
主要使用場景有兩個:
1.限制一些屬性為唯讀
在只使用@property修飾某個方法後,將其變成特定的屬性,如果不新增setter和deleter方法,那麼它就變成了唯讀屬性。比如:使用者名稱設定後就不允許修改:
class User: def __init__(self, username, password): self.__username = username self.password = password # 將username屬性限定為唯讀 @property def username(self): return self.__username if __name__ == '__main__': tom=User('tom','1234') print(tom.username) tom.username='Tom'
可以看到在唯讀狀態下,修改和刪除屬性都會失敗!
2.限定屬性的操作範圍
生活中,你可能會遇到這樣的情況,有一天你告訴你媽你想吃魚,並且是紅燒魚而不是清蒸魚,然後你媽命令你爸去買魚,同時你媽囑咐你爸說:買新鮮一點的啊,價格貴一點沒關係!然後你爸心想:這個月工資還沒發呢,能省省就省省吧,於是你爸在心中就大概確定了買一條魚的開銷區間(比如30到100)。可以看到在一條魚上餐桌之前,你和你爸媽是對它進行了精挑細選,才得以上到你的餐桌,其實就是對魚這個屬性增加了一些條件限定:型別的限定:要紅燒的而不是清蒸的;取值範圍的限定:不能太貴也不能太便宜,30到100之前剛剛好。
接下來用程式碼實現一下這個栗子:
class Fish: def __init__(self): self.__price = None self.__cook = None @property def price(self): return self.__price @price.setter def price(self, pri): if not isinstance(pri, int): raise ValueError('價格有誤!') if pri < 30: raise ValueError('太便宜了,不要!') elif pri > 100: raise ValueError('太貴了,不要!') else: self.__price = pri print('價格剛剛好!') @property def cook(self): return self.__price @cook.setter def cook(self,method): if method!='紅燒': raise ValueError('我只要紅燒魚!') else: print('耶,我最愛的紅燒魚!') if __name__ == '__main__': luck_fish=Fish() luck_fish.price=60 # luck_fish.cook='清蒸' luck_fish.cook='紅燒'
可以看到,只有當屬性的取值返回和型別是規定的範圍之內的時候,程式才會正常執行,而生活中類似這樣的栗子很多,所以這也是特性存在的意義。
直觀的看,特性的目的好像是把方法“屬性化”,但這樣做一點意義也沒有,如果我可以定義一個屬性,何必再額外定義一個方法,然後將其轉化成屬性呢?所以,更重要的目的就是應對一些特定場景。
從特性表現出來的性質和行為來看,它其實就是一種特定的“屬性”。只不過特性的權利提升了一點點,就好像你可以去修改這個屬性,但是能不能修改成功,就看你的上一級允不允許你修改(有沒有給你這個屬性新增限定條件),而特性的權利就擴充套件到了這個“上一級”。
在寫程式的時候,也不乏會出現這樣的例子:屬性和特性之間重名了!那麼這個時候在使用這個重名的屬性(特性)時,程式是會報錯?還是會使用屬性的值?還是會使用特性的值?也許根據它們的名稱就可以猜出來,特性嘛,肯定就特別一些嘛,所以會優先使用特性的值!下面這個栗子完美說明:
# 關係:在同名的情況下,範例屬性會覆蓋類屬性,特性會覆蓋範例屬性 class Cat: @property def wow(self): return 'property---喵~' if __name__ == '__main__': # 範例屬性會覆蓋類屬性 jerry = Cat() # 特性會覆蓋範例屬性 print(jerry.__dict__) # 檢視物件的屬性字典 jerry.__dict__['wow'] = 'normal---喵~' print(jerry.__dict__) print(jerry.wow) # 雖然修改了jerry的wow的值,但是依舊返回的是其特性的值 print(jerry.__dict__['wow']) del Cat.wow # 刪除類特性後,返回的就是正常的屬性值 # del Cat.wow # 刪除特性 print(jerry.wow) Cat.wow = property(lambda self: 'add a property---喵~') # 為類新增和屬性同名的特性 print(jerry.wow) # 之後還是優先存取特性的值
到此這篇關於python中的property及屬性與特性之間的優先權的文章就介紹到這了,更多相關python property 內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45