Python 模塊化 from .. import 語句介紹 (二)


from語句


例1、

from pathlib import Path,PosixPath

print(dir())
print(Path)
print(PosixPath)

運行結果:
['Path', 'PosixPath',...]
<class 'pathlib.Path'>
<class 'pathlib.PosixPath'>

  Path和PosixPath是pathlib模塊中定義的類,使用 "from .. import .."語句能夠直接映射pathlib模塊中的資源在當前的命名空間。接下來就可使用資源名直接調用,不須要再以"pathlib.Path" 這樣的完整資源層次關係調用。python

 

例2、

from pathlib import Path,PosixPath
import pathlib.Path

print(dir())
print(Path)
print(PosixPath)
print(pathlib.Path)

運行結果:
Traceback (most recent call last):
File "C:/python/1207.py", line 2, in <module>
import pathlib.Path
ImportError: No module named 'pathlib.Path'; 'pathlib' is not a package

  

包的簡單概念:
包必須是目錄,且此目錄下有一個__init__.py,好比下面的層級關係:編程

|--包windows

   |--__init__.py
   |--子模塊.py
   |--子模塊
      |--子模塊.py函數


包下面能夠有多個嵌套的子模塊,後面會單獨一篇文章介紹包。ui


模塊必須是一個文件夾或者單獨的以py結尾的文件,好比下面的層級關係:
|--os
   |--path.pyspa

上面的樹狀文件路徑中os是一個頂級模塊,path是os模塊下的一個子模塊。blog


再看下pathlib的層級關係:
|--pathlib.py
   |--class Path(PurePath)
上面的pathlib就是一個單獨的頂級模塊,Path只是這個模塊中的一個類,並非一個模塊,因此import pathlib.Path 直接導入時會拋出 No module named 'pathlib.Path' 異常。內存


若是須要直接導入模塊裏面的資源就必須使用 from 模塊 import 資源名 的格式,下一個例子就會介紹這種格式。資源

 

例3、

from pathlib import * #導入模塊下的全部"公共"資源

print(dir())
print(Path.cwd())
運行結果:
['Path', 'PosixPath', 'PurePath', 'PurePosixPath', 'PureWindowsPath', 'WindowsPath', ...]

  

經過前一個例子的異常,咱們知道import 沒法直接導入頂級模塊或子模塊中的資源(類,方法,屬性),使用 from .. import * 語句(第一種方法)就會將指定模塊下的全部資源導入,或者指定資源名的格式導入部分資源: from .. import 資源(第二種方法) ,這兩種方法都會將資源同名映射到當前命名空間。
第二種方法相比第一種方法的好處是,只導入須要的資源,其它用不到的資源統統不導入,能夠節省內存,這是一種好的編程習慣,在程序效率上任何微小的提高積累起來都是大的提高。it

本例子中特別強調了 from .. import * 導入的是模塊下的全部」公共「資源,公共資源也就是不以單下劃線(_xx)或者雙下劃線(__yy__)開頭的資源。

 

例4、

from os import path as osp #別名
print(dir())

運行結果:
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'osp']

  在導入子模塊或者資源時也可使用as 語句重命名子,當前命名空間最終保存的就是重命名後的映射。


例5、

from os.path import exists

print(dir())
if exists('c:/windows'):
print('found')
else:
print('not found')

運行結果:
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'exists']
found

  當前例子中使用了 from 包.模塊 import 子模塊 的格式,說明from語句後的模塊能夠是完整層級關係下的模塊(依然有一個找模塊、加載模塊、初始化模塊的過程),也能夠是單獨的模塊,最終當前加入命名空間的依然是子模塊名的映射。

 

例6、

from os.path import exists

print(dir())
print(exists)

import os
print(dir())
print(os.path.exists)
print(os.path.__dict__['exists'])

運行結果:
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'exists']
<function exists at 0x000001F7AEDAC268>
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'exists', 'os']
<function exists at 0x000001F7AEDAC268>
<function exists at 0x000001F7AEDAC268>

  

當前例子中前後使用不一樣的導入方式,導入path模塊的exists函數,最終比較內存地址時,按道理說先後調用的方式是不同的,卻發現內存地址是一致的。
模塊加載機制中可能有一種在當前環境中防止重複導入模塊的機制,下一篇文章再作介紹。


總結:

1. from 語句須要指定模塊,模塊能夠是單獨的頂級模塊,也能夠是層級關係下的子模塊,加載並初始化該模塊

2. import 語句後指定的是該模塊的資源(類,方法,函數),或者導入該模塊下的子模塊。

     先查找導入的模塊是具備該名稱的屬性 -->若是沒有,就嘗試導入爲該名稱的子模塊 --> 若是尚未找到,就拋出ImportError異常。下一篇文章也會舉例介紹該模塊搜索順序。

     若是該名稱後有as語句,則關聯as語句後的名稱到當前名詞空間

相關文章
相關標籤/搜索