Python深入03 對象的屬性

来源:https://www.cnblogs.com/king8/archive/2018/08/19/9499355.html
-Advertisement-
Play Games

  Python一切皆對象(object),每個對象都可能有多個屬性(attribute)。Python的屬性有一套統一的管理方案。   屬性的__dict__系統 對象的屬性可能來自於其類定義,叫做類屬性(class attribute)。類屬性可能來自類定義自身,也可能根據類 ...


 

Python一切皆對象(object),每個對象都可能有多個屬性(attribute)。Python的屬性有一套統一的管理方案。

 

屬性的__dict__系統

對象的屬性可能來自於其類定義,叫做類屬性(class attribute)。類屬性可能來自類定義自身,也可能根據類定義繼承來的。一個對象的屬性還可能是該對象實例定義的,叫做對象屬性(object attribute)。

對象的屬性儲存在對象的__dict__屬性中。__dict__為一個詞典,鍵為屬性名,對應的值為屬性本身。我們看下麵的類和對象。chicken類繼承自bird類,而summer為chicken類的一個對象。

複製代碼
class bird(object):
    feather = True

class chicken(bird):
    fly = False
    def __init__(self, age):
        self.age = age

summer = chicken(2)

print(bird.__dict__)
print(chicken.__dict__)
print(summer.__dict__)
複製代碼

 

下麵為我們的輸出結果:

複製代碼
{'__dict__': <attribute '__dict__' of 'bird' objects>, '__module__': '__main__', '__weakref__': <attribute '__weakref__' of 'bird' objects>, 'feather': True, '__doc__': None}


{'fly': False, '__module__': '__main__', '__doc__': None, '__init__': <function __init__ at 0x2b91db476d70>}


{'age': 2}
複製代碼

 

第一行為bird類的屬性,比如feather。第二行為chicken類的屬性,比如fly和__init__方法。第三行為summer對象的屬性,也就是age。有一些屬性,比如__doc__,並不是由我們定義的,而是由Python自動生成。此外,bird類也有父類,是object類(正如我們的bird定義,class bird(object))。這個object類是Python中所有類的父類。

可以看到,Python中的屬性是分層定義的,比如這裡分為object/bird/chicken/summer這四層。當我們需要調用某個屬性的時候,Python會一層層向上遍歷,直到找到那個屬性。(某個屬性可能出現再不同的層被重覆定義,Python向上的過程中,會選取先遇到的那一個,也就是比較低層的屬性定義)。

當我們有一個summer對象的時候,分別查詢summer對象、chicken類、bird類以及object類的屬性,就可以知道summer對象所有的__dict__,就可以找到通過對象summer可以調用和修改的所有屬性了。下麵兩種屬性修改方法等效:

summer.__dict__['age'] = 3
print(summer.__dict__['age'])

summer.age = 5
print(summer.age)

 

 (上面的情況中,我們已經知道了summer對象的類為chicken,而chicken類的父類為bird。如果只有一個對象,而不知道它的類以及其他信息的時候,我們可以利用__class__屬性找到對象的類,然後調用類的__base__屬性來查詢父類)

 

特性

同一個對象的不同屬性之間可能存在依賴關係。當某個屬性被修改時,我們希望依賴於該屬性的其他屬性也同時變化。這時,我們不能通過__dict__的方式來靜態的儲存屬性。Python提供了多種即時生成屬性的方法。其中一種稱為特性(property)。特性是特殊的屬性。比如我們為chicken類增加一個特性adult。當對象的age超過1時,adult為True;否則為False:

複製代碼
class bird(object):
    feather = True

class chicken(bird):
    fly = False
    def __init__(self, age):
        self.age = age
    def getAdult(self):
        if self.age > 1.0: return True
        else: return False
    adult = property(getAdult)   # property is built-in

summer = chicken(2)

print(summer.adult)
summer.age = 0.5
print(summer.adult)
複製代碼

 

特性使用內置函數property()來創建。property()最多可以載入四個參數。前三個參數為函數,分別用於處理查詢特性、修改特性、刪除特性。最後一個參數為特性的文檔,可以為一個字元串,起說明作用。

 

我們使用下麵一個例子進一步說明:

複製代碼
class num(object):
    def __init__(self, value):
        self.value = value
    def getNeg(self):
        return -self.value
    def setNeg(self, value):
        self.value = -value
    def delNeg(self):
        print("value also deleted")
        del self.value
    neg = property(getNeg, setNeg, delNeg, "I'm negative")

x = num(1.1)
print(x.neg)
x.neg = -22
print(x.value)
print(num.neg.__doc__)
del x.neg
複製代碼

 

上面的num為一個數字,而neg為一個特性,用來表示數字的負數。當一個數字確定的時候,它的負數總是確定的;而當我們修改一個數的負數時,它本身的值也應該變化。這兩點由getNeg和setNeg來實現。而delNeg表示的是,如果刪除特性neg,那麼應該執行的操作是刪除屬性value。property()的最後一個參數("I'm negative")為特性negative的說明文檔。

 

使用特殊方法__getattr__

我們可以用__getattr__(self, name)來查詢即時生成的屬性。當我們查詢一個屬性時,如果通過__dict__方法無法找到該屬性,那麼Python會調用對象的__getattr__方法,來即時生成該屬性。比如:

複製代碼
class bird(object):
    feather = True

class chicken(bird):
    fly = False
    def __init__(self, age):
        self.age = age
    def __getattr__(self, name):
        if name == 'adult':
            if self.age > 1.0: return True
            else: return False
        else: raise AttributeError(name)

summer = chicken(2)

print(summer.adult)
summer.age = 0.5
print(summer.adult)

print(summer.male)
複製代碼

 

每個特性需要有自己的處理函數,而__getattr__可以將所有的即時生成屬性放在同一個函數中處理。__getattr__可以根據函數名區別處理不同的屬性。比如上面我們查詢屬性名male的時候,raise AttributeError。

(Python中還有一個__getattribute__特殊方法,用於查詢任意屬性。__getattr__只能用來查詢不在__dict__系統中的屬性)

__setattr__(self, name, value)和__delattr__(self, name)可用於修改和刪除屬性。它們的應用面更廣,可用於任意屬性。

 

即時生成屬性的其他方式

即時生成屬性還可以使用其他的方式,比如descriptor(descriptor類實際上是property()函數的底層,property()實際上創建了一個該類的對象)。有興趣可以進一步查閱。

 

總結

__dict__分層存儲屬性。每一層的__dict__只存儲該層新增的屬性。子類不需要重覆存儲父類中的屬性。

即時生成屬性是值得瞭解的概念。在Python開發中,你有可能使用這種方法來更合理的管理對象的屬性。

 

如果你喜歡這篇文章,歡迎推薦


技術推動進步,分享促進社區。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 冒泡排序是一種基礎排序演算法,在python中,我們利用列表的的方式來完成,它對列表中的元素進行重覆的遍歷,在遍歷的同時進行比較,如果兩個數沒有按照我們規定的順序進行排列,就按照我們預先設定好的是順序或者逆序輸出,類似於燒開水時的氣泡,主要操作如下:比較相鄰的元素。如果第一個比第二個大(升序),就交換... ...
  • 設置 vim ~/.zshrc設置 vim ~/.bash_profile ...
  • c/c++ 淺拷貝 編譯器合成的 拷貝構造函數 和 =重載函數 ,只是做入下處理: 如果成員變數a是指針,執行完 拷貝構造函數 或者 =重載函數 後,對象1和對象2的成員變數就指向了一個地址了,所以當改變對象1的a的值,對象2的a的值也變化了, 而且,如果在析構函數里寫了free(a)的話,就相當於 ...
  • c/c++ 編譯器提供的預設6個函數 1,構造函數 2,拷貝構造函數 3,析構函數 4,=重載函數 5,&重載函數 6,const&重載函數 c++ include using namespace std; class Test{ public: Test(int d = 0):data(d){ c ...
  • 前言 上一章我們知道瞭如何使用幾何著色器將頂點通過流輸出階段輸出到綁定的頂點緩衝區。接下來我們繼續利用它來實現一些新的效果,在這一章,你將瞭解: 1. 實現公告板效果 2. Alpha To Coverage 3. 對GPU資源進行讀/寫操作 4. 紋理數組 5. 實現霧效 "DirectX11 W ...
  • 1.查看是否已經安裝Python CentOS 7.2 預設安裝了python2.7.5 因為一些命令要用它比如yum 它使用的是python2.7.5。 使用 python -V 命令查看一下是否安裝Python 然後使用命令 which python 查看一下Python可執行文件的位置 可見執 ...
  • 裝飾器(decorator)是一種高級Python語法。裝飾器可以對一個函數、方法或者類進行加工。在Python中,我們有多種方法對函數和類進行加工,比如在Python閉包中,我們見到函數對象作為某一個函數的返回結果。相對於其它方式,裝飾器語法簡單,代碼可讀性高。因此,裝飾器在Python項目中有廣 ...
  • 靜態語言 在編寫代碼時,必須為變數指定一個明確類型的語言。比如Java、C/C++ 動態語言 在編寫代碼時,不必為變數指定一個明確的類型,而是由解釋器在運行時根據變數的使用情況確定變數的類型。比如python、javascript 強類型語言 變數必須有一個確定的類型。比如Java、C/C++、py ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...