最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

python魔法方法-屬性訪問控制詳解

 更新時(shí)間:2016年07月25日 08:59:33   投稿:jingxian  
下面小編就為大家?guī)硪黄猵ython魔法方法-屬性訪問控制詳解。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧

屬性訪問控制

所謂的屬性訪問控制就是控制點(diǎn)號(hào)訪問屬性的行為,而且不僅是類的外部,連類的內(nèi)部也受控制,代碼見真章,邊看代碼邊解釋:

•__getattr__(self, item)

定義當(dāng)訪問不存在的屬性時(shí)的行為,注意是不存在的屬性。

class Foo(object):
  def __init__(self, value):
    self.value = value

  def __getattr__(self, item):
    print item # 查看得到的參數(shù)是什么
    print type(item)  # 參數(shù)的類型是什么
    return 'attr:%s' % item # 最后返回一個(gè)東西看其行為如何

a = Foo('scolia')  # 創(chuàng)建一個(gè)實(shí)例

測(cè)試:

print a.value
print type(a.value)

其行為和沒定義前正常,下面看看訪問一個(gè)不存在的屬性時(shí)會(huì)發(fā)生什么:

print a.abc

按照平常的情況,訪問不存在的屬性時(shí)肯定會(huì)拋出異常,但是這里輸出了三行,前兩個(gè)是方法輸出的,最后一行是外部的print語(yǔ)句輸出的,輸出的是方法的return值。方法得到的是我們?cè)L問的屬性名,而且是以字符串的形式。

知道了以上信息后,我們就可以定制更多:

class Foo(object):
  def __init__(self, value):
    self.value = value

  def __getattr__(self, item):
    if item == 'scolia':
      return 'can not set attr: %s' % item # 訪問不存在的scolia屬性時(shí),打印一句話而不報(bào)錯(cuò)
    else:
      raise AttributeError('not attr name: %s' % item)  # 訪問其他不存在的屬性時(shí),觸發(fā)異常。

測(cè)試:

a = Foo(123)
print a.value # 訪問存在的屬性

print a.scolia # 訪問不存在的屬性,但我們做了特殊處理的

沒有觸發(fā)異常,和我們?cè)O(shè)想的一樣。

print a.good # 訪問不存在的屬性,但應(yīng)該觸發(fā)異常的

觸發(fā)了我們想要的異常。

這里要再?gòu)?qiáng)調(diào)一遍,必須是訪問不存在的屬性時(shí),才會(huì)調(diào)用這個(gè)方法,例如:

a.scolia = 321
print a.scolia

因?yàn)檫@個(gè)屬性已經(jīng)存在了(我們手動(dòng)添加了),所以訪問它的時(shí)候并沒有調(diào)用這個(gè)方法,而在方法里所做的任何處理,也不會(huì)有效。

更高級(jí)的技巧:

class Foo(object):
  def __init__(self, value, defulat=None):
    self.value = value
    self.__defulat = defulat

  def __getattr__(self, item):
    item = item.lower() # 用字符串的方法對(duì)其進(jìn)行小寫
    if item in self.__dict__:
      return self.__dict__[item] # 返回相應(yīng)的屬性
    else:
      self.__dict__[item] = self.__defulat  # 若屬性不存在則添加這個(gè)屬性并使用默認(rèn)值
      return self.__dict__[item]

a = Foo(123)
a.scolia = 321
print a.SCOlia
print a.good

我們實(shí)現(xiàn)了屬性的不區(qū)分大小寫訪問和自動(dòng)添加不存在的屬性。

這里的秘訣在于活用 __dict__ 這個(gè)屬性,我在類的屬性中已經(jīng)討論過這個(gè)屬性。這個(gè)屬性由python自動(dòng)創(chuàng)建,是一個(gè)字典,包含對(duì)象的所有屬性,字典里的鍵就是屬性名,對(duì)應(yīng)的值就是屬性值。所以這里在這個(gè)字典中添加了鍵和值,就相當(dāng)于為對(duì)象添加了屬性和屬性值。

•__setattr__(self, key, value)

定義了設(shè)置屬性時(shí)的行為,包括在 __init__ 初始化函數(shù)中的設(shè)置行為:

class Foo(object):
  def __init__(self, value, defulat=None):
    self.value = value

  def __setattr__(self, key, value):
    print key, type(key)
    print value, type(value)

a = Foo('scolia')
b = Foo(123)

這里可以看到初始化函數(shù)中的屬性添加的行為也受到了控制,其中 key 得到的是屬性名,以字符串的形式;而 value 得到的是屬性值,屬性值根據(jù)輸入的不同而不同。

在這里,我們僅僅只是打印了幾句話,而沒有進(jìn)行屬性的添加,所以當(dāng)我們?cè)噲D訪問相應(yīng)的屬性時(shí),會(huì)發(fā)現(xiàn)根本就沒有:

print a.value

觸發(fā)了異常,表示沒有相應(yīng)的屬性。

知道了這些之后我們可以做很多事情,例如將所有的屬性名變成小寫或大寫,控制某些屬性名不能添加之類的,就不再舉例。不過,這里你總不可能用 self.key = value 來添加屬性吧,因?yàn)?key 始終是一個(gè)字符串。這個(gè)時(shí)候就要使用 __dict__ 屬性了,向這個(gè)字典中添加相應(yīng)的鍵值對(duì)就可以了,具體就不再演示了。

•__delattr__(self, item)

定義了刪除一個(gè)屬性時(shí)的行為,item 得到的也是一個(gè)字符串形式的屬性名,具體細(xì)節(jié)也無序多說,只要 del 掉 __dict__ 字典中對(duì)應(yīng)是鍵和值就行了。另外,刪除不存在的屬性時(shí)調(diào)用的也是這個(gè)方法。

•__getattribute__(self, name)

這個(gè)方法定義了所有屬性訪問的行為,注意是所有,而不是 __getattr__ 中的不存在。當(dāng)實(shí)現(xiàn)了這個(gè)方法之后,將會(huì)覆蓋 __getattr__ 方法,畢竟所有涵蓋了不存在。

這個(gè)方法只在新式類中有效。

但是,你也可以顯式的調(diào)用 __getattr__,例如 a.__getattr__ 來使用這個(gè)被掩蓋的方法,或者是觸發(fā) AttributeError 異常時(shí)也會(huì)自動(dòng)調(diào)用它。

然而,非常不建議使用這個(gè)方法,因?yàn)榭赡軙?huì)很多不可預(yù)知的異常情況,最常見的就是無盡的遞歸調(diào)用,例如:

class Foo(object):
  def __init__(self, value):
    self.value = value

  def __getattribute__(self, item):
    return self.__dict__[item]

a = Foo('scolia')
print a.value

這段代碼看起來很正常,但是這里有一個(gè)陷阱,因?yàn)轭愔械乃械膶傩栽L問都是受這幾個(gè)魔法方法控制的,包括上面介紹的幾個(gè)魔法方法。它們似乎比普通的魔法方法擁有更高的權(quán)限一般。

但這就導(dǎo)致了一個(gè)問題,例如這里的 self.__dict__[item] ,這句話也受屬性訪問的控制,盡管這個(gè)屬性是 python 為我們創(chuàng)建的。

也就是說獲取 self.__dict__ 時(shí),會(huì)再次調(diào)用 __getattribute__ 方法,然后方法內(nèi)又調(diào)用了 self.__dict__ 。這樣無限循環(huán)下去,最終會(huì)拋出一個(gè)異常。

異常信息非常長(zhǎng),這里我是拉到最后才截的圖。

其實(shí)不僅這個(gè)魔法方法會(huì)導(dǎo)致這樣異常,上面討論的幾種魔法方法可能都會(huì)出現(xiàn)這個(gè)問題,只不過這個(gè)魔法方法的權(quán)限更大,所以異常出現(xiàn)的可能性更高一些。

這也就是不推薦這個(gè)魔法方法的原因,而使用其他的屬性控制方法的時(shí)候也要小心。

而到目前為止,我們所學(xué)到的屬性訪問的方法只有兩種,一是直接用點(diǎn)號(hào)訪問,還有就是先通過點(diǎn)號(hào)訪問__dict__ 屬性,然后在這個(gè)字典中獲取相應(yīng)的鍵值對(duì)。而這兩種方法都受到了 __getattribute__ 的控制,調(diào)用它們就相當(dāng)于沒有終點(diǎn)的自調(diào)用(有終點(diǎn)的自調(diào)用有時(shí)能提升效率),那么這個(gè)方法到底要怎么用呢?

技巧就是調(diào)用父類的這個(gè)方法:

class Foo(object):
  def __init__(self, value):
    self.value = value

  def __getattribute__(self, item):
    return object.__getattribute__(self, item) # 非綁定方法要顯式傳遞self

a = Foo('scolia')
print a.value

這里調(diào)用的是object的這個(gè)方法,如果是涉及到繼承的話:

class Boo(Foo):
  def __init__(self, value):
    self.value = value

  def __getattribute__(self, item):
    return Foo.__getattribute__(self, item)
    # return super(Boo, self).__getattribute__(item)  也可以使用super函數(shù)讓python自動(dòng)在其父類們尋找這個(gè)方法。
a = Foo('scolia')
print a.value
b = Boo(123)
print b.value

訪問正常。

其實(shí)最后調(diào)用了還是 object 或其他內(nèi)置類型的方法。

而我們姑且不起探究object到底是怎么實(shí)現(xiàn)的,因?yàn)檫@可能是用 C 所寫的,只要會(huì)用就可以,雖然這個(gè)方法用的也不多。

最后附上一個(gè)完整的例子:

class Foo(object):
  def __init__(self, value):
    self.value = value

  def __getattr__(self, item):
    if item == 'scolia':
      return 'no attr:%s' % item
    elif item in self.__dict__:
      return self.__dict__[item]
    else:
      raise AttributeError('no attr:%s' % item)

  def __setattr__(self, key, value):
    if key == 'good':
      print 'can not set the attr: good'
    else:
      self.__dict__[key] = value

  def __delattr__(self, item):
    if item == 'a':
      print 'no attr: good'
    else:
      del self.__dict__[item]

  def __getattribute__(self, item):
    if item == 'a':
      raise AttributeError('not a')
    return object.__getattribute__(self, item)


a = Foo('scolia')
print a.value  # 正常訪問
a.a = 123  # __getattribute__會(huì)觸發(fā)AttributeError異常,此時(shí)調(diào)用__getattr__
      # 而__getattr__添加了這個(gè)屬性,所以最后異常沒有觸發(fā),屬性也添加了
print a.a  # 結(jié)果能夠訪問
del a.a # 試圖刪除這個(gè)屬性
print a.a # 刪除行為被阻止了,所以該屬性還在
a.good = 'good' # 因?yàn)樘砑颖蛔柚沽?
print a.good # 所以訪問失敗了

結(jié)果:

以上這篇python魔法方法-屬性訪問控制詳解就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Pygame實(shí)戰(zhàn)練習(xí)之飛機(jī)大戰(zhàn)游戲

    Pygame實(shí)戰(zhàn)練習(xí)之飛機(jī)大戰(zhàn)游戲

    飛機(jī)大戰(zhàn)想必是很多人童年時(shí)期的經(jīng)典游戲,我們依舊能記得抱個(gè)老人機(jī)娛樂的場(chǎng)景,下面這篇文章主要給大家介紹了關(guān)于如何利用python寫一個(gè)簡(jiǎn)單的飛機(jī)大戰(zhàn)小游戲的相關(guān)資料,需要的朋友可以參考下
    2021-09-09
  • 利用Python開發(fā)Markdown表格結(jié)構(gòu)轉(zhuǎn)換為Excel工具

    利用Python開發(fā)Markdown表格結(jié)構(gòu)轉(zhuǎn)換為Excel工具

    在數(shù)據(jù)管理和文檔編寫過程中,我們經(jīng)常使用 Markdown 來記錄表格數(shù)據(jù),但它沒有Excel使用方便,所以本文將使用Python編寫一個(gè)轉(zhuǎn)換工具,希望對(duì)大家有所幫助
    2025-03-03
  • Python 爬蟲學(xué)習(xí)筆記之正則表達(dá)式

    Python 爬蟲學(xué)習(xí)筆記之正則表達(dá)式

    正則表達(dá)式是用來匹配字符串非常強(qiáng)大的工具,在其他編程語(yǔ)言中同樣有正則表達(dá)式的概念,Python同樣不例外,利用了正則表達(dá)式,我們想要從返回的頁(yè)面內(nèi)容提取出我們想要的內(nèi)容就易如反掌了。
    2016-09-09
  • python?import?引用上上上級(jí)包的三種方法

    python?import?引用上上上級(jí)包的三種方法

    這篇文章主要介紹了python?import?引用上上上級(jí)包的三種方法包的三種方法,需要的朋友可以參考下
    2023-02-02
  • 教你用python實(shí)現(xiàn)12306余票查詢

    教你用python實(shí)現(xiàn)12306余票查詢

    今天就和大家一起來討論一下python實(shí)現(xiàn)12306余票查詢(pycharm+python3.7),一起來感受一下python爬蟲的簡(jiǎn)單實(shí)踐,需要的朋友可以參考下
    2021-06-06
  • 解決python遞歸函數(shù)及遞歸次數(shù)受到限制的問題

    解決python遞歸函數(shù)及遞歸次數(shù)受到限制的問題

    這篇文章主要介紹了解決python遞歸函數(shù)及遞歸次數(shù)受到限制的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • 利用python判斷字母大小寫的幾種方法小結(jié)

    利用python判斷字母大小寫的幾種方法小結(jié)

    在開發(fā)過程中有時(shí)候我們需要判斷一個(gè)字符串是否是小寫形式,下面這篇文章主要給大家介紹了關(guān)于利用python判斷字母大小寫的幾種方法,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-05-05
  • python中os.path.dirname(path)詳細(xì)解釋和使用示例

    python中os.path.dirname(path)詳細(xì)解釋和使用示例

    這篇文章主要介紹了python中os.path.dirname(path)詳細(xì)解釋和使用示例,os.path.dirname是一個(gè)Python函數(shù),用于獲取文件路徑的目錄部分,它通常與os.path.basename結(jié)合使用,以分離路徑中的目錄和文件名,需要的朋友可以參考下
    2025-03-03
  • Python中使用第三方庫(kù)xlrd來寫入Excel文件示例

    Python中使用第三方庫(kù)xlrd來寫入Excel文件示例

    這篇文章主要介紹了Python中使用第三方庫(kù)xlrd來寫入Excel文件示例,本文講解了安裝xlwt、API介紹、使用xlwt寫入Excel文件實(shí)例,需要的朋友可以參考下
    2015-04-04
  • Python中的異常處理簡(jiǎn)明介紹

    Python中的異常處理簡(jiǎn)明介紹

    這篇文章主要介紹了Python中的異常處理簡(jiǎn)明介紹,本文講解了try-except檢測(cè)異常、上下文管理器(with…as…語(yǔ)句)、raise引發(fā)異常、斷言等內(nèi)容,需要的朋友可以參考下
    2015-04-04

最新評(píng)論

高安市| 平南县| 浦北县| 磐石市| 湘西| 永靖县| 陵川县| 托里县| 库尔勒市| 远安县| 宝鸡市| 乐平市| 岳西县| 贡嘎县| 灵丘县| 常熟市| 丹江口市| 济阳县| 韩城市| 陆河县| 延安市| 南皮县| 马关县| 旺苍县| 西昌市| 道孚县| 中方县| 卫辉市| 桦甸市| 房山区| 商都县| 镇坪县| 阜康市| 伊宁县| 新郑市| 海丰县| 杭锦旗| 临澧县| 广灵县| 普宁市| 隆林|