Python 入門 24 —— import 導入、 __name__、 __main__

除了內置對象,標準庫對象和擴展庫對象在使用前都需要用 import 導入。

一、導入模塊

(1)基本語句:import 模塊名 [as 模塊別名]

導入模塊後就可以使用模塊中的類、函數、對象等東東了,不過在使用時要加上“模塊名.”這個前綴。爲了簡化前綴,在導入時可以用“as 模塊別名”的方式,給模塊取個別名。不過取了別名之後,原名就失效了。例如:

import datetime
d = datetime.date.today()
t = datetime.datetime.now()
print(d,t)    # 2020-02-03     2020-02-03 11:35:20.937157

print(dir(datetime))    # 查看模塊中的所有對象:['MAXYEAR',... 'tzinfo']
print(dir(datetime.date))    # 查看類中所有成員:['__add__',... 'weekday', 'year']

import datetime as dt    # 給datetime取個別名
d01 = dt.date.today()
t01 = dt.datetime.now()
print(d01,t01)    # 2020-02-03     2020-02-03 11:37:21.739067
d02 = datetime.date.today()    # 原名失效:NameError: name 'datetime' is not defined

(2)同時導入多個模塊:import 模塊1名 [as 模塊1別名], 模塊2名 [as 模塊2別名], …
例如:

import os, sys , datetime as dt, math    # 同時導入 os、sys、datetime、math
print(dt.date.today(), math.ceil(2.98))    # 2020-02-03    3

二、導入模塊中的對象

(1)基本語句:from 模塊名 import 對象名 [as 對象別名]

這種方式導入的不是整個模塊中的所有對象,而是指定的對象。通過這種方式導入的對象,在使用時,不需要加上“模塊名.”這個前綴。當然,這也帶來一個問題:在導入多個模塊的情況下,如果有對象重名的現象,重名的對象會相互屏蔽。在導入時也可以給對象另取別名。例如:

from datetime import date    # 僅導入 date

print(date.today())    # 2020-02-03
print(datetime.date.today())    # 不要前綴:NameError: name 'datetime' is not defined
print(datetime.now())    # 沒有導入:NameError: name 'datetime' is not defined

(2)同時導入多個對象:from 模塊名 import 對象1名 [as 對象1別名], 對象2名 [as 對象2別名], …

例如:

from datetime import date as dd, datetime as tt
print(dd.today(), tt.now())    # 2020-02-03    2020-02-03 12:57:32.903249

(3)導入模塊中的所有對象:from 模塊名 import *

例如:

from datetime import *
print(date.today(), datetime.now())    # 2020-02-03 2020-02-03 12:59:41.594610

三、導入自定義的模塊

導入自定義模塊與導入標準庫模塊的語句是一樣的,但因爲標準庫模塊是系統自己存放的,且一般統一放在固定的目錄中,所以,導入時一般不用考慮路徑問題,而自定義的模塊就不一樣了,如果不弄清楚模塊的存放目錄,系統就會找不到模塊文件,從而使導入失敗。

在import 語句中是不可以指定模塊所在目錄的。例如: mport c:/mymod,這個語句是錯誤的。

1、當前目錄

系統在導入模塊時,首先在當前目錄中查找模塊文件。例如:在命令行窗口中,提示符爲:D:\py>,則首先在 D:\py 目錄中查找模塊文件,找到了模塊文件就立即導入。

2、sys.path 中列出的目錄

系統如果在當前目錄中沒有找到模塊文件,則在查看 sys.path 中列出的目錄,然後按照前後順序,在各個目錄中查找,找到了就導入,找不到就拋出異常:ModuleNotFoundError。

(1)查看 sys.path 中已有哪些目錄:print(sys.path)。

例如:

import sys
print(sys.path)    # ['D:\\py\\python38.zip', 'D:\\py']

(2)在 sys.path 目錄列表的最後添加目錄:sys.path.append(目錄名)。

例如:

import sys
sys.path.append('D:\\aa')
sys.path.append('D:\\bb')
sys.path.append('D:\\cc')

print(sys.path)    # ['D:\\py\\python38.zip', 'D:\\py', 'D:\\aa', 'D:\\bb', 'D:\\cc']

(3)在 sys.path 目錄列表的指定序號前插入目錄:sys.path.insert(序號,目錄名)

例如:

import sys;
sys.path.append('D:\\aa')
sys.path.insert(2,'D:\\dd')
sys.path.insert(0,'D:\\ee')

print(sys.path)    # ['D:\\ee', 'D:\\py\\python38.zip', 'D:\\py', 'D:\\dd', 'D:\\aa']

在設置好目錄後,就可以導入自定義的模塊了。例如:

建立文件:E:\testpy\py05.py ,內容如下:

class c01:pass
class c02:pass
def fun01():pass
def fun02():pass

導入 p05 模塊:

import sys
sys.path.append('E:\\testpy')
import py05
print(dir(py05))
# ['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__',
# '__package__', '__spec__', 'c01', 'c02', 'fun01', 'fun02']

print(sys.path)    # ['D:\\py\\python38.zip', 'D:\\py', 'E:\\testpy']

四、導入自定義包

假設有以下自定義的包和模塊:

pybao(E:/testpy/)
    __init__.py
    baopy01.py
    baopy02.py
    pybao01
        __init__.py
    pybao02
        __init__.py
        baopy03.py
        baopy04.py
        pybao11
            __init__.py
            baopy05.py
        pybao12
            __init__.py
            baopy06.py
            baopy07.py
            baopy08.py
            baopy09.py

也就是說:
E:/testpy目錄中有:pybao包
pybao包中有:pybao01包、pybao02包
pybao02包中有:pybao11包、pybao12包

(1)基本語句:import 包名

與導入自定義模塊一樣,導入自定義包也有一個定位問題。系統同樣是先在當前目錄中查找,找不到就查看 sys.path 中列出的目錄,然後按照前後順序,在各個目錄中查找,再找不到就拋出異常。

“import 包名” 這一語句並不是將包中的所有模塊和對象導入,它唯一的結果是促使包中的 “__ init__.py” 被執行。

例如:E:/testpy/pybao/init.py 的內容爲:

print('This is __init__.py of pybao')
import sys
sys.path.append('E:\\testpy')

import pybao    # This is __init__.py of pybao

“__ init__.py”被執行之後,如果在這個文件中有導入的語句,則相應的模塊和對象,就會被導入。例如:E:/testpy/pybao/__ init__.py 的內容爲:

print('This is __init__.py of pybao')

import sys
sys.path.append('E:\\testpy\\pybao')
import baopy01,baopy02

以這種方式導入的模塊,在引用時要加上“包名.”這個前綴,例如:

import sys
sys.path.append('E:\\testpy')
import pybao    # This is __init__.py of pybao
print(dir(pybao.baopy01))    # [... 'c11', 'c12', 'fun11', 'fun12']
print(dir(pybao.baopy02))    # [... 'c21', 'c22', 'fun21', 'fun22']

總之,“import 包名” 不會直接導入任何的模塊和對象,只會觸發包中的 __ init__.py 文件被執行。

(2)導入包中的包:import 大包名.小包名. …

在導入過程中,大包、小包中的 __ init__.py 文件的都會被執行。例如:

E:/testpy/pybao/__ init__.py 的內容爲:

print('This is __init__.py of pybao')

E:/testpy/pybao02/__ init__.py 的內容爲:

print('This is __ init__.py of pybao02')

E:/testpy/pybao12/__ init__.py 的內容爲:

print('This is __init__.py of pybao12')

導入包:pybao12

import sys
sys.path.append('E:\\testpy')
import pybao.pybao02.pybao12
# 顯示:
# This is __init__.py of pybao
# This is __init__.py of pybao02
# This is __init__.py of pybao12

(3)直接導入包中的模塊:import 包名.模塊名

在導入過程中,包中的 __ init__.py 文件的會先被執行,然後導入包。例如:

E:/testpy/pybao/init.py 的內容爲:

print('This is __init__.py of pybao')

導入 pybao 包中的 baopy01.py 模塊:

import sys
sys.path.append('E:\\testpy')

import pybao.baopy01    # This is __init__.py of pybao
print(dir(pybao.baopy01))    # [... 'c11', 'c12', 'fun11', 'fun12']

以這種方式導入的模塊,在引用時也要加上“包名.”這個前綴,例如:

(4)直接導入包中的多個模塊:from 包名 import *

這一語句不是直接導入包中的所有模塊,而導入 “__ init__.py” 文件中, __ all__變量指定的模塊。例如:

E:/testpy/pybao/pybao02/pybao12/init.py 的內容爲:

print('This is __init__.py of pybao12')
__all__=[baopy05,baopy06]

導入pybao12的模塊:

import sys
sys.path.append('E:\\testpy')

from pybao.pybao02.pybao12 import *
# 顯示:
# This is __init__.py of pybao
# This is __init__.py of pybao02
# This is __init__.py of pybao12

print(dir(baopy05))    # [...  'c51', 'c52', 'fun51', 'fun52']
print(dir(baopy06))    # [...  'c61', 'c62', 'fun61', 'fun62']
print(dir(baopy08))    # [...  'c81', 'c82', 'fun81', 'fun82']
print(dir(baopy09))    # NameError: name 'baopy09' is not defined

以這種方式導入的模塊,在引用時不需要 “包名.” 這個前綴。

五、 __ name__ 和 __ main__

模塊被導入後,系統將它轉化成“模塊對象”,並且還會爲模塊對象缺省添加上一些數據成員。例如:
E:/testpy/py06.py 的內容爲:

class c06:pass
import sys
sys.path.append('E:\\testpy')
import py06
print(dir(py06))
# 顯示:
# ['__builtins__', '__cached__', '__doc__', '__file__',
# '__loader__', '__name__', '__package__', '__spec__', 'c06']

模塊對象中有一個名爲“ __ name__”的數據成員比較常用。當模塊被直接執行時,系統將“模塊對象”的 __ name__值置爲“ __ main__”,當模塊被導入後再直接執行時模塊的 __ name__值置爲“模塊名”。例如:
E:/testpy/py06.py 的內容爲:

class c06:pass;  print('py06 __name__:',__name__)
import sys
sys.path.append('E:\\testpy')

import py06    # py06 __name__: py06

print('my __name__:',__name__)    # my __name__: __main__

在實際編程中,經常通過 name 的值來判斷一個模塊是否處在被導入中,以此來避免一些語句在導入時被執行。例如:

if __name__ == '__main__':    # 噹噹前模塊被導入時,以下這些語句不會被執行
    x = 100
    y = 200
    z = 300

———————————————— 本篇完 ————————————————

看完之後,麻煩您順手點擊下方 “點贊” 兩個字給我點個贊吧 ^-^ , 謝謝您了。

如果您還能像我小學一年級班主任好老師那樣,給我隨心寫上幾句表揚或批評的話語,那真是感激不盡!

在我人生的道路上,有了您的鼓勵和指導,我一定成長快快。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章