我 的 個(gè) 人 主 頁(yè):???? 失心瘋的個(gè)人主頁(yè) ????
入 門 教 程 推 薦 :???? Python零基礎(chǔ)入門教程合集 ????
虛 擬 環(huán) 境 搭 建 :???? Python項(xiàng)目虛擬環(huán)境(超詳細(xì)講解) ????
PyQt5 系 列 教 程:???? Python GUI(PyQt5)文章合集 ????
Oracle數(shù)據(jù)庫(kù)教程:???? Oracle數(shù)據(jù)庫(kù)文章合集 ????
優(yōu) 質(zhì) 資 源 下 載 :???? 資源下載合集 ????文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-730338.html
文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-730338.html
只讀屬性
概念
- 一個(gè)屬性(一般指實(shí)例屬性),只能讀取,不能寫(xiě)入
應(yīng)用場(chǎng)景
- 有些屬性,只限在內(nèi)部根據(jù)不同場(chǎng)景進(jìn)行修改,對(duì)外界來(lái)說(shuō),不能修改,只能讀取
實(shí)現(xiàn)方法
方式一:使用property裝飾器
- 步驟
- 1、通過(guò)私有化全部隱藏(既不能讀,也不能寫(xiě))
- 2、通過(guò)方法部分公開(kāi)(公開(kāi)讀的操作)
- 示例
class Person: def __init__(self): self.__age = 18 def getAge(self): return self.__age p = Person() # print(p.__age) # 報(bào)錯(cuò),通過(guò)屬性私有化,隱藏了讀操作 # p.__age = 22 # 并不是修改的私有屬性,而是新增了__age屬性。通過(guò)屬性私有化,隱藏了寫(xiě)操作 print(p.getAge()) # 通過(guò)指定方法,公開(kāi)讀操作
- 存在問(wèn)題
- 1、獲取屬性的時(shí)候需要通過(guò)調(diào)用方法獲取
p.getAge()
,而不是通過(guò)屬性獲取方式獲取p.age
- 2、在外部直接使用賦值
p.age = 22
并不會(huì)報(bào)錯(cuò)(雖然沒(méi)有修改內(nèi)部的私有屬性,而是給實(shí)例添加了一個(gè)age屬性,但是給人的感覺(jué)就是修改了)
- 1、獲取屬性的時(shí)候需要通過(guò)調(diào)用方法獲取
- 優(yōu)化
class Person: def __init__(self): self.__age = 18 # @property的作用:裝飾器,可以使用屬性的方式調(diào)用這個(gè)方法 @property def age(self): return self.__age p = Person() print(p.age) # 18 # p.age = 22 # 報(bào)錯(cuò),AttributeError: can't set attribute
- 通過(guò)優(yōu)化之后,就可以通過(guò)調(diào)用屬性的方式調(diào)用讀屬性方法了。并且,外部也不能對(duì)這個(gè)屬性方法進(jìn)行賦值
- 缺陷
- 通過(guò)裝飾器的方式設(shè)置的只讀屬性,其實(shí)還是可以通過(guò)
_Person__age
這種改名之后的方式進(jìn)行修改 - 也可以通過(guò)
實(shí)例.__dict__['_Person__age'] = 新值
的方式修改這個(gè)只讀屬性的值
- 通過(guò)裝飾器的方式設(shè)置的只讀屬性,其實(shí)還是可以通過(guò)
方式二:使用__setattr__方法進(jìn)行判斷
- 步驟
- 當(dāng)通過(guò) 實(shí)例.屬性=值 的方式給實(shí)例添加一個(gè)屬性或修改屬性的值時(shí)候,會(huì)自動(dòng)調(diào)用該方法
- 在這個(gè)方法內(nèi)部,增加判定方法,滿足條件后才把這個(gè)屬性添加到
__dict__
這個(gè)字典中
- 代碼說(shuō)明
class Person(object): # 當(dāng)通過(guò) 實(shí)例.屬性=值 的方式給實(shí)例添加一個(gè)屬性或修改屬性的值時(shí)候,會(huì)自動(dòng)調(diào)用該方法 # 在這個(gè)方法內(nèi)部,才會(huì)真正的把這個(gè)屬性添加到 __dict__ 這個(gè)字典中 def __setattr__(self, key, value): # key:屬性 value:屬性值 print(key, value) p = Person() p.age = 12 # age 12
- 使用
__setattr__
設(shè)置只讀屬性class Person(object): def __init__(self): self.__age = 18 pass @property def age(self): return self.__age # 當(dāng)通過(guò) 實(shí)例.屬性=值 的方式給實(shí)例添加一個(gè)屬性或修改屬性的值時(shí)候,會(huì)自動(dòng)調(diào)用該方法 # 在這個(gè)方法內(nèi)部,才會(huì)真正的把這個(gè)屬性添加到 __dict__ 這個(gè)字典中 def __setattr__(self, key, value): # key:屬性 value:屬性值 # print(key, value) if key == 'age': print('隱藏屬性,不可修改', key) return # self.key = value # 不能這么寫(xiě),這樣寫(xiě)也是通過(guò) 實(shí)例.屬性=值 的方式給實(shí)例添加一個(gè)屬性或修改屬性的值,會(huì)循環(huán)調(diào)用__setattr__方法,出現(xiàn)死循環(huán) # 只能通過(guò)下面的方法給實(shí)例添加/修改屬性 self.__dict__[key] = value p = Person() print(p.age) # 18 p.age = 22 # 隱藏屬性,不可修改 age print(p.age) # 18
補(bǔ)充_裝飾器property詳解
property作用
- 將一些“屬性的操作方法(刪、改、查)”關(guān)聯(lián)到某一個(gè)屬性中
class Person(object):
def __init__(self):
self.__age = 18
@property
def age(self, num):
"""屬性的操作方法:獲取屬性值"""
return self.__age
property源碼
- preoperty源碼說(shuō)明
class property(object): """ Property attribute. property(fget=None, fset=None, fdel=None, doc=None) -> property ottribute # 調(diào)用property函數(shù),傳入四個(gè)參數(shù),返回一個(gè)屬性 # 作用:將一個(gè)屬性的幾個(gè)操作方法(刪、改、查)關(guān)聯(lián)到返回的這個(gè)屬性里面 # 讀取這個(gè)屬性的時(shí)候會(huì)自動(dòng)調(diào)用第一個(gè)參數(shù):fget方法 # 設(shè)置這個(gè)屬性的值會(huì)自動(dòng)調(diào)用第二個(gè)參數(shù):fset方法 # 刪除合格屬性的時(shí)候會(huì)自動(dòng)調(diào)用第三個(gè)參數(shù):fdel方法 fget function to be used for getting an attribute value # 用于獲取屬性值的函數(shù) fset function to be used for setting an attribute value # 用于設(shè)置屬性值的函數(shù) fdel function to be used for del'ing an attribute # 用于刪除屬性值的函數(shù) doc docstring Typical use is to define a managed attribute x: # 典型的用法是定義一個(gè)定義和管理一個(gè)屬性x: class C(object): def getx(self): return self._x def setx(self, value): self._x = value def delx(self): del self._x x = property(getx, setx, delx, "I'm the 'x' property.") Decorators make defining new properties or modifying existing ones easy: # 裝飾器使定義新屬性或修改現(xiàn)有屬性變得容易: class C(object): @property def x(self): "I am the 'x' property." return self._x # 必須先開(kāi)啟上面的@property裝飾器 @x.setter def x(self, value): self._x = value @x.deleter def x(self): del self._x """
補(bǔ)充:經(jīng)典類和新式類
-
經(jīng)典類
- 概念:沒(méi)有繼承自object的類
-
新式類
- 概念:繼承自object的類和其派生類
-
示例
# 在Python2.x 版本中 class Person: pass class Animal(object): pass # 查看基類(父類) print(Person.__base__) # () print(Animal.__base__) # <class 'object'> # =================================================== # 在Python3.x 版本中 class Person: pass class Animal(object): pass # 查看基類(父類) print(Person.__base__) # <class 'object'> print(Animal.__base__) # <class 'object'>
- 在Python2.x版本中
- 定義一個(gè)類的時(shí)候,沒(méi)有顯示的繼承自object類,那么這個(gè)類就是一個(gè)經(jīng)典類
- 必須顯示的繼承自object類,才是一個(gè)新式類
- 在Python3.x版本中
- 定義一個(gè)類的時(shí)候,沒(méi)有顯示的繼承自pbject類時(shí),會(huì)隱式的(默認(rèn))繼承自object類,這個(gè)類就是一個(gè)新式類
- 在通常情況下,我們一般都寫(xiě)成顯示繼承(即:定義的類繼承自object時(shí),也用
class Person(object)
的方式定義)
property在兩種類中的使用方式
property在新式類中的使用方式
- 使用方式一
class Person(object): def __init__(self): # 定義一個(gè)屬性__age self.__age = 18 def get_age(self): """定義一個(gè)__age屬性的操作方法(查)""" print('執(zhí)行g(shù)et_age方法') return self.__age def set_age(self, num): """定義一個(gè)__age屬性的操作方法(改)""" print('執(zhí)行set_age方法') self.__age = num # 調(diào)用property方法,使age屬性與get_age、set_age方法進(jìn)行關(guān)聯(lián) # 在獲取age屬性的值時(shí),自動(dòng)調(diào)用property函數(shù)的第一個(gè)參數(shù):get_age方法 # 在設(shè)置age屬性的值時(shí),自動(dòng)調(diào)用property函數(shù)的第二個(gè)參數(shù):seg_age方法 age = property(get_age, set_age) p = Person() print(p.age) # 執(zhí)行g(shù)et_age方法 18 p.age = 36 # 執(zhí)行set_age方法 print(p.age) # 執(zhí)行g(shù)et_age方法 36 print(p.__dict__) # {'_Person__age': 36},可以看出來(lái),賦值方式并沒(méi)有給對(duì)象增加新的屬性,而是直接修改了原本的屬性值
- 使用方式二
class Person(object): def __init__(self): self.__age = 18 @property def age(self): print("執(zhí)行了@property裝飾的age方法") return self.__age @age.setter def age(self, num): print("執(zhí)行了@age.setter裝飾的age方法") self.__age = num @age.deleter def age(self): print("執(zhí)行了@age.deleter裝飾的age方法") del self.__age p = Person() print(p.age) # 執(zhí)行了@property裝飾的age方法 18 p.age = 36 # 執(zhí)行了@age.setter裝飾的age方法 print(p.__dict__) # {'_Person__age': 36} del p.age # 執(zhí)行了@age.deleter裝飾的age方法
property在經(jīng)典類中的使用方式(在Python2.x版本中運(yùn)行)
- 使用方式一
# Python2.x版本運(yùn)行 # 定義一個(gè)經(jīng)典類,不繼承自object類 class Person: def __init__(self): self.__age = 18 def get_age(self): print '執(zhí)行了get_age方法' return self.__age def set_age(self, num): print '執(zhí)行了set_age方法' self.__age = num age =property(get_age, set_age) p = Person() print p.age # 執(zhí)行了get_age方法 p.age = 36 # print(p.__dict__) # {'age': 36, '_Person__age': 18} # 可以看出來(lái),在經(jīng)典類中,屬性的賦值操作并不能關(guān)聯(lián)到property函數(shù)的第二個(gè)參數(shù)
- 使用方式二
# Python2.x版本運(yùn)行 # 定義一個(gè)經(jīng)典類,不繼承自object類 class Person: def __init__(self): self.__age = 18 @property def age(self): print '執(zhí)行了get_age方法' return self.__age @age.setter def age(self, num): print '執(zhí)行了set_age方法' self.__age = num p = Person() print p.age # 執(zhí)行了get_age方法 18 p.age = 36 # print(p.__dict__) # {'age': 36, '_Person__age': 18}
- 通過(guò)示例可以看出來(lái),在經(jīng)典類中,雖然我們可以定義裝飾屬性賦值操作的方法,但是并不能真正的將這個(gè)操作方法與賦值操作進(jìn)行關(guān)聯(lián)
到了這里,關(guān)于030.Python面向?qū)ο骭類&補(bǔ)充_只讀屬性的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!