1. 程式人生 > >python之塊包導入

python之塊包導入

訪問 引用 class .py 都是 而且 支持 報錯 不支持

一、模塊

  1、什麽是模塊

    常見的場景:一個模塊就是一個包含了python定義和聲明的文件,文件名就是模塊名字加上.py的後綴。

    但其實import加載的模塊分為四個通用類別: 

    1 使用python編寫的代碼(.py文件)

    2 已被編譯為共享庫或DLL的C或C++擴展

    3 包好一組模塊的包

    4 使用C編寫並鏈接到python解釋器的內置模塊

  2、為什麽要使用模塊

    如果你退出python解釋器然後重新進入,那麽你之前定義的函數或者變量都將丟失,因此我們通常將程序寫到文件中以便永久保存下來,需要時就通過python test.py方式去執 行,此時test.py被稱為腳本script。

隨著程序的發展,功能越來越多,為了方便管理,我們通常將程序分成一個個的文件,這樣做程序的結構更清晰,方便管理。這時我們不僅僅可以把這些文件當做腳本去執行, 還可以把他們當做模塊來導入到其他的模塊中,實現了功能的重復利用

  3、如何使用模塊

    3.1 import

    示例文件:spam.py,文件名spam.py,模塊名spam       

spam.py
print(from the spam.py)

money=1000

def read1():
    print(spam->read1->money,money)

def read2(): print(spam->read2 calling read) read1() def change(): global money money=0

    3.1.1 模塊只在模塊名第一次遇到導入import語句時才執行(import語句是可以在程序中的任意位置使用的,且針對同一個模塊很import多次,為了防止你重復導入,python的優化 手段是:第一次導入後就將模塊名加載到內存了,後續的import語句僅是對已經加載大內存中的模塊對象增加了一次引用,不會重新執行模塊內的語句)

#test.py
import spam #只在第一次導入時才執行spam.py內代碼,此處的顯式效果是只打印一次‘from the spam.py‘,當然其他的頂級代碼也都被執行了,只不過沒有顯示效果.
import spam
import spam
import spam

‘‘‘
執行結果:
from the spam.py
‘‘‘

  我們可以從sys.module中找到當前已經加載的模塊,sys.module是一個字典,內部包含模塊名與模塊對象的映射,該字典決定了導入模塊時是否需要重新導入。

  3.1.2 每個模塊都是一個獨立的名稱空間,定義在這個模塊中的函數,把這個模塊的名稱空間當做全局名稱空間,這樣我們在編寫自己的模塊時,就不用擔心我們定義在自己模塊 中全局變量會在被導入時,與使用者的全局變量沖突

  3.1.3總結:首次導入模塊spam時會做三件事:

    1.為源文件(spam模塊)創建新的名稱空間,在spam中定義的函數和方法若是使用到了global時訪問的就是這個名稱空間。

    2.在新創建的命名空間中執行模塊中包含的代碼,見初始導入import spam

    3.創建名字spam來引用該命名空間

   3.1.4 為模塊名起別名

    import spam as sm

    3.1.5在一行導入多個模塊

    import sys,os,re

    3.2 from...import...

    3.2.1 對比import spam,會將源文件的名稱空間‘spam‘帶到當前名稱空間中,使用時必須是spam.名字的方式

而from 語句相當於import,也會創建新的名稱空間,但是將spam中的名字直接導入到當前的名稱空間中,在當前名稱空間中,直接使用名字就可以了、

      from spam import read1,read2
    這樣在當前位置直接使用read1和read2就好了,執行時,仍然以spam.py文件全局名稱空間
    如果當前有重名read1或者read2,那麽會有覆蓋效果。
    需要特別強調的一點是:python中的變量賦值不是一種存儲操作,而只是一種綁定關系
    
    3.2.2 也支持as
    from spam import read1 as read
    3.2.3 也支持導入多行
    from spam import (read1,
                  read2,
                   money)
    3.2.4 from spam import * 把spam中所有的不是以下劃線(_)開頭的名字都導入到當前位置,大部分情況下我們的python程序不應該使用這種導入方式,因為*你不知道你導入什麽名字,很有可能會覆蓋掉你之前已經定義的名字。而且可讀性極其的差,在交互式環境中導入時沒有問題。

    
可以使用__all__來控制*(用來發布新版本)

    在*.py中新增一行

    __all__=[‘money‘,‘read1‘] #這樣在另外一個文件中用from spam import *就這能導入列表中規定的兩個名字

    可以使用__all__來控制*(用來發布新版本)

    如果spam.py中的名字前加_,即_money,則from spam import *,則_money不能被導入

    3.2.5 考慮到性能的原因,每個模塊只被導入一次,放入字典sys.module中,如果你改變了模塊的內容,你必須重啟程序,python不支持重新加載或卸載之前導入的模塊,

    3.3 把模塊當做腳本執行

    我們可以通過模塊的全局變量__name__來查看模塊名:

    當做腳本運行:
    __name__ 等於‘__main__‘

    當做模塊導入:
    __name__=

    作用:用來控制.py文件在不同的應用場景下執行不同的邏輯
    if __name__ == ‘__main__‘:

    3.4模塊搜索路徑

    python解釋器在啟動時會自動加載一些模塊,可以使用sys.modules查看

    在第一次導入某個模塊時(比如spam),會先檢查該模塊是否已經被加載到內存中(當前執行文件的名稱空間對應的內存),如果有則直接引用

    如果沒有,解釋器則會查找同名的內建模塊,如果還沒有找到就從sys.path給出的目錄列表中依次尋找spam.py文件。

    所以總結模塊的查找順序是:內存中已經加載的模塊->內置模塊->sys.path路徑中包含的模塊

    3.5編譯python文件

    為了提高加載模塊的速度。python解釋器會在__pycache__目錄中下緩存每個模塊編譯後的版本,格式為: module.version.pyc。通常會包含python的版本號。例如,在 CPython3.3版本下,spam.py模塊會被緩存成__pycache__/spam.cpython-33.pyc。這種命名規範保證了編譯後的 結果多版本共存。

二、包

  包是一種通過使用‘.模塊名’來組織python模塊名稱空間的方式。

  1. 無論是import形式還是from...import形式,凡是在導入語句中(而不是在使用時)遇到帶點的,都要第一時間提高警覺:這是關於包才有的導入語法

  2. 包是目錄級的(文件夾級),文件夾是用來組成py文件(包的本質就是一個包含__init__.py文件的目錄)

  3. import導入文件時,產生名稱空間中的名字來源於文件,import 包,產生的名稱空間的名字同樣來源於文件,即包下的__init__.py,導入包本質就是在導入該文件

強調:

  1. 在python3中,即使包下沒有__init__.py文件,import 包仍然不會報錯,而在python2中,包下一定要有該文件,否則import 包報錯

  2. 創建包的目的不是為了運行,而是被導入使用,記住,包只是模塊的一種形式而已,包即模塊

  _init__.py文件

  不管是哪種方式,只要是第一次導入包或者是包的任何其他部分,都會依次執行包下的__init__.py文件(我們可以在每個包的文件內都打印一行內容來驗證一下),這個文件可以為空,但是也可以存放一些初始化包的代碼。

   2.2 from glance.api import *

    在講模塊時,我們已經討論過了從一個模塊內導入所有*,此處我們研究從一個包導入所有*。

      此處是想從包api中導入所有,實際上該語句只會導入包api下__init__.py文件中定義的名字,我們可以在這個文件中定義__all___:

   2.3 絕對導入和相對導入

    導入和相對導入兩種方式:

    絕對導入:以glance作為起始

    相對導入:用.或者..的方式最為起始(只能在一個包中使用,不能用於不同目錄內)

    特別需要註意的是:可以用import導入內置或者第三方模塊(已經在sys.path中),但是要絕對避免使用import來導入自定義包的子模塊(沒有在sys.path中),應該使用 from... import ...的絕對或者相對導入,且包的相對導入只能用from的形式。

   2.4單獨導入包

    單獨導入包名稱時不會導入包中所有包含的所有子模塊,如

 

python之塊包導入