Python中模組的使用

RunTitan發表於2018-05-31
  • 做過開發工作的童鞋應該都知道, 在一個完整的專案中, 會有大量的程式碼, 而且慢慢程式碼量會越來越多, 程式碼也就越來越難以維護;
  • 隨著你的程式變得越來越長,你可能想要將它分割成幾個更易於維護的檔案。
  • 你也可能想在不同的程式中使用順手的函式,而不是把程式碼在它們之間中拷來拷去
  • 為了解決類似問題, 我們把很多功能相似的函式分組, 分別放到不同的檔案中,這樣每個檔案中的程式碼相對較少, 且函式功能相似;
  • GitHub程式碼示例目地址

概述

模組簡述

  • Python中提供了一個方法可以從檔案中獲取定義,在指令碼或者直譯器的一個互動式例項中使用, 這樣的檔案被稱為模組;
  • 模組中的定義可以匯入到另一個模組或主模組中(在指令碼執行時可以呼叫的變數集位於最高階,並且處於計算器模式)
  • 模組是包括 Python 定義和宣告的檔案。檔名就是模組名加上 .py 字尾。
  • 模組的模組名(做為一個字串)可以由全域性變數 __name__ 得到
  • 模組主要分為內建模組, 三方模組和自定義模組

模組優點

  • 提高了程式碼的可維護性
  • 提高了程式碼的服用度, 當一個模組完畢, 可以被多個地方引用
  • 可避免函式名和變數名的衝突

標準庫模組

下面是一個使用python標準庫中模組的例子

import sys

print('命令列引數如下:')
for i in sys.argv:
   print(i)

print('\n\nPython 路徑為:', sys.path, '\n')


# 輸出結果如下
命令列引數如下:
../GitHub/PythonDemo/PythonStudy/7-模組/1-模組概述.py

Python 路徑為: ['/Users/../GitHub/PythonDemo/PythonStudy/7-模組', '/Users/../GitHub/PythonDemo/PythonStudy', '/Library/Frameworks/Python.framework/Versions/3.6/lib/python36.zip', '/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6', '/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/lib-dynload', '/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages', '/Applications/PyCharm.app/Contents/helpers/pycharm_matplotlib_backend'] 
複製程式碼
  • argv: 獲取命令列引數的列表
  • import sys 引入python標準庫中的sys.py模組
  • import: 這是引入一個模組的方法(後面會提到)
  • sys.path: 包含了一個Python直譯器自動查詢所需模組的路徑的列表

自定義模組

  • Python中不但可以使用第三方模組和系統模組, 同時我們還可以使用自定義模組,
  • Python中一個.py檔案就是一個模組
  • 下面是我自定義的一個Titan.py模組, 程式碼如下
print('這是Titan模組')

# 定義變數
age = 20
name = 'titan'

# 定義方法
def sayGood():
    print('good')

def sayNice():
    print('nice')

def sayBad():
    print('bad')
複製程式碼

匯入模組

import方式

Python中匯入另一個檔案或者模組, 受用的語法是import

# 引入單個或多個模組
import module1[, module2[,... moduleN]

# 示例
# 一次匯入多個模組
import time, random, os
# 一次匯入一個模組
import calendar
複製程式碼

需要注意的是:

  • 一個模組只會被匯入一次,不管你執行了多少次import, 可以防止模組被重複引用
  • 引入任何模組時(包括自定義模組), 不用加.py字尾
  • 當我們使用import語句的時候,Python直譯器是怎樣找到對應的檔案的呢?
    • 這就涉及到Python的搜尋路徑,搜尋路徑是由一系列目錄名組成的,Python直譯器就依次從這些目錄中去尋找所引入的模組。
    • 這看起來很像環境變數,事實上,也可以通過定義環境變數的方式來確定搜尋路徑。
    • 搜尋路徑是在Python編譯或安裝的時候確定的,安裝新的庫應該也會修改。搜尋路徑被儲存在sys模組中的path變數

使用示例

import Titan

Titan.sayBad()
Titan.sayGood()
print(Titan.name)

# 輸出結果:
bad
good
titan
複製程式碼

from…import方式

從模組中匯入一個指定的部分到當前的名稱空間, 同樣也可以匯入一個模組中的多個部分(或者匯入多個方法或變數), 格式如下:

from modname import name1[, name2[, ... nameN]]
複製程式碼

使用示例

from Titan import sayGood, sayBad, age

sayBad()
sayGood()
print(age)

# 輸出結果:
bad
good
20
複製程式碼

需要注意的是:

這種方式, 可能會導致和本檔案中定義的方法或者變數重名, 這裡需要注意

from…import*方式

把一個模組中所有的內容, 全部倒入當前名稱空間, 但是最好不要過多地使用

# 格式:
from modname import *

# 使用:
from Titan import *
sayGood()
print(age)
複製程式碼

模組內建屬性和函式

__name__屬性

  • 除了包含函式定義外,模組也可以包含可執行語句, 這些語句一般用來初始化模組, 他們僅在第一次被匯入的地方執行一次
  • 模組就是一個可執行的.py檔案, 一個模組唄另一個程式引用, 模組中的一些可執行語句便會執行
  • 如果我們不想讓模組中的某些程式碼執行, 可以用__name__屬性來使程式僅呼叫模組中的一部分
  • 現在我們將模組中的程式碼修改如下:
if __name__ == '__main__':
    print('這是Titan模組')
else:
    def sayGood():
        print('good')


    def sayNice():
        print('nice')


    def sayBad():
        print('bad')


    age = 20
    name = 'titan'
複製程式碼
  • namemain前後都是雙下劃線
  • 每一個模組中都有一個__name__屬性, 當其值等於__main__時, 表明該模組自身在執行, 否則被引入了其他檔案
  • 當前檔案如果為程式的入口檔案, 則__name__屬性的值為__main__

dir()函式

  • 內建的函式dir() 可以找到模組內定義的所有名稱, 以一個字串列表的形式返回
  • 如果沒有給定引數,那麼dir()函式會羅列出當前定義的所有名稱
import Titan

print(dir(Titan))

# 輸出結果:
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'age', 'name', 'sayBad', 'sayGood', 'sayNice']


print(dir())
# 輸出結果:
['Titan', '__annotations__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__']


# 這裡定義一個新的變數
sum = 30
print(dir())
# 輸出結果:
['Titan', '__annotations__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'sum']


# 把定義的變數刪除後
del sum
print(dir())
# 輸出結果:
['Titan', '__annotations__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__']
複製程式碼

這裡我們先思考這樣一個問題: 在同一個專案中有兩個或兩個以上的開發者分別定義了相同名字的模組(當然獅子啊不同的目錄中, 同一個目錄下不可能建立出相同名字的檔案), 那麼模組該如何呼叫

解決

  • 為了解決上述模組命名的衝突, 引入了按照目錄來組織模組的方法, 成為包
  • 包是一種管理Python模組名稱空間的形式,採用"點模組名稱"
  • 引入包以後, 只要頂層的包不與其他人的發生衝突, 那麼模組就都不會與別人的發生衝突
  • 所謂頂層的包指的是上一層的檔案目錄
  • 同一個包可以包含多個模組
  • 例如: 名為A.B的模組表示了名為A的包中名為B的子模組

需要注意的是:

在每一個包內(模組的同級目錄下)必須要建立一個名為__init__.py的檔案, 主要是為了避免一些濫竽充數的名字, 目前該檔案內可以什麼都不用寫, 如圖所示:

包.png

呼叫方法

import a.Titan
import b.Titan
import b.coder

a.Titan.sayGood()
b.Titan.sayGood()
b.coder.sayGood()


# 輸出結果:
good--a
good--b
good--coder
複製程式碼

安裝使用第三方模組

pip簡介

  • Python中第三方庫是通過pip安裝和管理的, pip就像iOS中的pod一樣, 負責安裝和管理第三方庫
  • MacLinux系統中pip是預設安裝過的, 一般無需重新安裝, 如有問題, 請自行百度解決
  • Mac系統中會有一個預設的Python2.7版本的, 我自己安裝了一個3.6的版本, 自然預設也安裝了pip
  • 下面是一些Python3.6pip的命令, 這裡需要以pip3為命令頭執行
# 檢視當前pip版本
pip3 -V

# 安裝第三方庫
pip3 install ...

# 對pip進行升級
pip3 install --upgrade pip3
複製程式碼

安裝第三方庫

  • Mac系統安裝第三方庫, 直接開啟終端執行安裝命令即可
  • Pillow已經是Python平臺事實上的影像處理標準庫了
  • PIL功能非常強大,但API卻非常簡單易用
pip3 install Pillow
複製程式碼

第三方模組的使用

操作影像

下面是最常見的影像縮放操作示例程式碼

from PIL import Image

# 開啟一個jpg影像檔案,注意是當前路徑:
im = Image.open('titan.jpg')

# 獲得影像尺寸
w, h = im.size
print('image size: %sx%s' % (w, h))

# 縮放到50%:
im.thumbnail((w//2, h//2))
print('image to: %sx%s' % (w//2, h//2))

# 把縮放後的影像用jpeg格式儲存:
im.save('jun.jpg', 'jpeg')
複製程式碼

其他功能如切片、旋轉、濾鏡、輸出文字、調色盤等一應俱全, 程式碼如下:

from PIL import Image, ImageFilter

# 開啟一個jpg影像檔案,注意是當前路徑:
im = Image.open('jun.jpg')
# 應用模糊濾鏡:
im2 = im.filter(ImageFilter.BLUR)
im2.save('jun1.jpg', 'jpeg')
複製程式碼

相關參考


相關文章