1. 程式人生 > >一、開發基礎(3)

一、開發基礎(3)

例如 規則 來源 就會 絕對導入 直接 模塊名 組合類 私有變量

模塊

  • 模塊也是一個對象
    • 模塊的出現是為了代碼的重用
    • 通過模塊,將大型應用分解為小模塊,小模塊分別實現不同的功能
    • 使用模塊最重要的就是要避免循環導入
    • 模塊名/目錄名遵循命名語法規則
  • import如何工作
    • 第一次導入時,找到模塊文件,編譯成位碼,執行代碼創建其頂層定義的對象
    • 已經導入的模塊保存在sys.modules字典中
  • 模塊搜索路徑
    • 環境變量
    • sys.path列表,調用append方法,這種修改只在腳本運行時保持,退出就消失
  • 支持的導入格式
    • py
    • pyc
    • 包導入
    • 編譯拓展模塊等等
  • from和import
    • 都是賦值語句,import將整個模塊作為對象賦值給一個模塊名,from將一個或多個變量名賦值給同名對象
    • from賦值過來的變量名與其來源的文件沒有聯系,因此在reload時from導入的變量名可能還是之前的版本
  • reload
    • reload是內置函數,不是語句
    • 傳給reload的是已存在的模塊對象,不是變量
    • reload在Python3中位於模塊中,使用前必須先導入自己 from importlib import reload
    • import影響所有import導入的模塊和以後使用from的模塊,不影響之前的from
    • 包的目錄中必須有__init__.py文件
    • 包導入在模塊導入的基礎上拓展了本地作用域的概念,對模塊進行了更高一級的分組,就如同模塊是對程序的分解,包則是對模塊的分解
    • 相對導入 from . import module
      Python3中不帶.的導入總是先在sys.path的絕對路徑中查找
    • 使用絕對導入,sys.path需要包含包的根目錄,不如相對導入方便,並且相對導入只使用from語句
  • 模塊隱藏數據
    • 使用_X單下劃線命名的變量不會被導入,這種方法針對from module improt *語句
    • 在模塊頂層創建__all__列表,只放可以被導入的變量名,這種方法也是針對from module improt *語句
  • 循環導入
    • 常見的臨時解決辦法一是在函數內import,二是在模塊結尾導入,但都不是最好的辦法
    • 最好的辦法是對兩個模塊循環導入使用的功能進行抽象,放入一個單獨模塊文件中,讓這兩個模塊導入該單獨的模塊文件即可完成解耦

  • 類的概念
    • 其實就是一個高級的字典,除了提供屬性訪問,還提供了方法用於處理數據
    • 面向對象編程最重要的概念就是繼承和多態,而類很好的提供了這些功能
  • 類的屬性
    • 類屬性,所有實例共享
    • 實例屬性,既可以在__init__方法中初始化,也可以在實例化後進行賦值,這種屬性是每個實例獨有的,只能通過該實例對象訪問
  • 類的方法
    • 類方法,第一個參數是類(人為默認是cls),可以通過類名.方法調用,也可以通過實例.方法調用,但是無法在外部調用,相當於
    Test.classmethod(Test, *args, **kwargs)
    test.classmethod(test.__class__, *args, **kwargs)
    • 靜態方法,不接收類或實例作為參數,但是類和實例都能調用,與類方法沒什麽太大區別,唯一區別就是靜態方法內一般不會調用到類或實例對象
    • 實例方法,第一個參數是實例(人為默認是self),只能通過實例調用,會自動傳入實例本身
    • 魔法方法/運算符重載方法,Python類內置的一些方法,由於繼承機制,我們可以通過修改這些魔法方法中的內容來為我們的類添加一些特殊功能
      • 例如直接print實例,返回的是一個<__main__.object>這種對象,通過重載__str____repr__,在此print這個實例時會顯示一些我們定義的內容
      • 常見的魔法方法:(以下方法省略了頭尾的雙下劃線,在使用中記得補上)
        • new:創建實例對象
        • init:為實例對象的屬性進行初始化操作
        • del:對象收回,也稱析構方法,用了該方法的類創建的實例不會被gc自動回收,因此一般不會重寫這個方法
        • add:運算符+,左側加法,即實例對象在左側,如ins + 5
        • sub:運算符-,左側減法,即實例對象在左側,如ins - 5
        • or:運算符|
        • repr,str:打印,轉換,str只適用於print和str函數,__repr__可用於所有環境中,程序優先使用__str__
        • call:函數調用
        • getattr:點號運算
        • setattr:屬性賦值語句
        • delattr:屬性刪除
        • getattribute:屬性獲取
        • getitem:索引運算
        • setitem:索引賦值語句
        • delitem:索引和分片刪除
        • len:長度
        • bool:布爾測試
        • lt,gt,le,ge,eq,ne:<, >, <=, >=, ==, !=
        • radd:右側加法
        • iadd:增強加法+=
        • iter,next:叠代環境,前面寫過,__iter__對象返回自身即self,next返回下一個值,並且應該提供StopIteration異常
        • contains:成員關系測試,優先__contains__,其次__iter__,最後__getitem__
        • index:整數值
        • enter,exit:環境管理器,用於with方法的調用
        • get,set:描述符

          魔法方法早期學習時只要學__repr____init__即可,以後使用多了就會慢慢理解其它方法。

  • 類的繼承
    • 實例調用__class__獲取它的類,類通過__bases__獲取父類列表
    • Python中的類的繼承是用樹的形式來表達的,因此就出現了兩種繼承順序
      • Python2中按深度優先的順序進行繼承搜索,忽視右側
      • Python3中按廣度優先的順序進行繼承搜索,可以遍歷到所有繼承的類
      • 這種繼承在某些書中會稱為鉆石繼承,或MRO樹等,但其實就是以上兩種方法
    • 只要父類樹中某個類提供了方法,則其下的所有子類都將獲得這個方法,這種繼承使得功能不用重復實現了,只要繼承就可以了
    • 繼承方法的覆蓋,只要在子類中重寫了該方法,則子類的實例永遠無法調用到父類的方法,除非直接通過父類調用其類方法,解決辦法是在該方法中再調用父類的方法
  • 類的組合
    • 在實際業務中,可能會出現容器類,就是這個類的某個屬性調用了其它類並實例化,在這個類的方法中就能使用其它類的方法
    • 這種將其它類實例作為屬性參與到運行中,就是組合類,它有實現了不同類接口API的整合
  • 類的包裝
    • 與組合差不多,只是它接收的是類本身而不是類的實例
  • 類的多態
    • 有個說法就是鴨子類型,其實本身Python在多態方面就支持的比較好,如+在面對數字和字符串時表示的方法完全不同,但也能直接使用
    • 如果你自己的類需要實現多態,那麽魔法方法一定要學好,尤其是運算符部分的重載
  • 類的私有屬性
    • 在命名規則中有提到過數據隱藏
    • 類中單下劃線開頭的變量是由程序員指定的私有變量,但仍然可以被外部訪問
    • 雙下劃線開頭的變量在使用時會被自動拓展變量名,避免了重名,如__x變成了_class__x,會自動加單下劃線+類名
    • 類和實例調用__dict__獲取屬性字典
    • 在類中頂層定義__slots__列表,限制可以使用的屬性,如果父類沒有定義slots,則子類總可以訪問到父類的__dict__屬性
  • 元類
    • 看這裏
  • 類的特性和Mixin多重繼承
    • 回頭再寫這部分

一、開發基礎(3)