草根學Python(八) 模塊與包

前言

以前的文章都是使用Sublime Text來編寫 Python 的,主要是爲了更好的熟悉和了解 Python ,但是開發效率不高,也不方便,從這章開始,改成使用 Pycharm 了,在以前的篇節集成開發環境(IDE): PyCharm中介紹了 PyCharm ,若是如要激活軟件能夠經過受權服務器來激活,具體看這個網址。JetBrains激活(http://www.imsxm.com/jetbrains-license-server.html)固然你也能夠嘗試破解, Pycharm2017.1.1破解方式,不過對於軟件的升級不方便。html

目錄

草根學Python(八)  模塊與包
草根學Python(八) 模塊與包

1、Python 模塊簡介

在開發過程當中,隨着程序代碼越寫越多,在一個文件裏代碼就會愈來愈長,愈來愈不容易維護。python

爲了編寫可維護的代碼,咱們把不少函數分組,分別放到不一樣的文件裏,這樣,每一個文件包含的代碼就相對較少,不少編程語言都採用這種組織代碼的方式。在 Python 中,一個 .py 文件就稱之爲一個模塊(Module)。android

以前咱們學習過函數,知道函數是實現一項或多項功能的一段程序 。其實模塊就是函數功能的擴展。爲何這麼說呢?那是由於模塊其實就是實現一項或多項功能的程序塊。編程

經過上面的定義,不難發現,函數和模塊都是用來實現功能的,只是模塊的範圍比函數廣,在模塊中,能夠有多個函數。服務器

居然瞭解了什麼是模塊了,那麼爲何須要模塊呢?居然有了函數,那爲啥那須要模塊?微信

最大的好處是大大提升了代碼的可維護性。其次,編寫代碼沒必要從零開始。當一個模塊編寫完畢,就能夠被其餘地方引用。咱們在編寫程序的時候,也常常引用其餘模塊,包括 Python 內置的模塊和來自第三方的模塊。編程語言

使用模塊還能夠避免函數名和變量名衝突。相同名字的函數和變量徹底能夠分別存在不一樣的模塊中,所以,咱們本身在編寫模塊時,沒必要考慮名字會與其餘模塊衝突。可是也要注意,儘可能不要與內置函數名字衝突。函數

Python 自己就內置了不少很是有用的模塊,只要安裝完畢,這些模塊就能夠馬上使用。咱們能夠嘗試找下這些模塊,好比個人 Python 安裝目錄是默認的安裝目錄,在 C:\Users\Administrator\AppData\Local\Programs\Python\Python36 ,而後找到 Lib 目錄,就能夠發現裏面所有都是模塊,沒錯,這些 .py 文件就是模塊了。性能

python36bin目錄
python36bin目錄

其實模塊能夠分爲標準庫模塊和自定義模塊,而剛剛咱們看到的 Lib 目錄下的都是標準庫模塊。學習

2、模塊的使用

一、import

Python 模塊的使用跟其餘編程語言也是相似的。你要使用某個模塊,在使用以前,必需要導入這個模塊。導入模塊咱們使用關鍵字 import

import 的語法基本以下:

import module1[, module2[,... moduleN]複製代碼

好比咱們使用標準庫模塊中的 math 模塊。當解釋器遇到 import 語句,若是模塊在當前的搜索路徑就會被導入。

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-

import math

_author_ = '兩點水'

print(math.pi)複製代碼

輸出的結果:

3.141592653589793複製代碼

一個模塊只會被導入一次,無論你執行了多少次 import。這樣能夠防止導入模塊被一遍又一遍地執行。

當咱們使用 import 語句的時候,Python 解釋器是怎樣找到對應的文件的呢?

這就涉及到 Python 的搜索路徑,搜索路徑是由一系列目錄名組成的,Python 解釋器就依次從這些目錄中去尋找所引入的模塊。這看起來很像環境變量,事實上,也能夠經過定義環境變量的方式來肯定搜索路徑。搜索路徑是在 Python 編譯或安裝的時候肯定的,安裝新的庫應該也會修改。搜索路徑被存儲在sys 模塊中的 path 變量 。

所以,咱們能夠查一下路徑:

#!/usr/bin/env python
# -*- coding: UTF-8 -*-

import sys

print(sys.path)複製代碼

輸出結果:

['C:\\Users\\Administrator\\Desktop\\Python\\Python8Code', 'G:\\PyCharm 2017.1.4\\helpers\\pycharm', 'C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python36\\python36.zip', 'C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python36\\DLLs', 'C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python36\\lib', 'C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python36', 'C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python36\\lib\\site-packages', 'C:\\Users\\Administrator\\Desktop\\Python\\Python8Code\\com\\Learn\\module\\sys']複製代碼

二、from···import

有沒有想過,怎麼直接導入某個模塊中的屬性和方法呢?

Python 中,導入一個模塊的方法咱們使用的是 import 關鍵字,這樣作是導入了這個模塊,這裏須要注意了,這樣作只是導入了模塊,並無導入模塊中具體的某個屬性或方法的。而咱們想直接導入某個模塊中的某一個功能,也就是屬性和方法的話,咱們可使用 from···import 語句。

語法以下:

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

看完簡介後可能會想, from···importimport 方法有啥區別呢?

想知道區別是什麼,觀察下面兩個例子:

import 導入 sys 模塊,而後使用 version 屬性

from···import和 import的區別1
from···import和 import的區別1

from···import 直接導入 version 屬性

from···import和 import的區別2
from···import和 import的區別2

三、from ··· import *

經過上面的學習,咱們知道了 from sys import version 能夠直接導入 version 屬性。可是若是咱們想使用其餘的屬性呢?好比使用 sys 模塊中的 executable ,難道又要寫多一句 from sys import executable ,兩個還好,若是三個,四個呢?難道要一直這樣寫下去?

這時候就須要 from ··· import * 語句了,這個語句能夠把某個模塊中的全部方法屬性都導入。好比:

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-

from sys import *

print(version)
print(executable)複製代碼

輸出的結果爲:

3.6.1 (v3.6.1:69c0db5, Mar 21 2017, 18:41:36) [MSC v.1900 64 bit (AMD64)]
C:\Users\Administrator\AppData\Local\Programs\Python\Python36\python.exe複製代碼

注意:這提供了一個簡單的方法來導入一個模塊中的全部方法屬性。然而這種聲明不應被過多地使用。

3、主模塊和非主模塊

一、主模塊和非主模塊的定義

在 Python 函數中,若是一個函數調用了其餘函數完成一項功能,咱們稱這個函數爲主函數,若是一個函數沒有調用其餘函數,咱們稱這種函數爲非主函數。主模塊和非主模塊的定義也相似,若是一個模塊被直接使用,而沒有被別人調用,咱們稱這個模塊爲主模塊,若是一個模塊被別人調用,咱們稱這個模塊爲非主模塊。

二、name 屬性

在 Python 中,有主模塊和非主模塊之分,固然,咱們也得區分他們啊。那麼怎麼區分主模塊和非主模塊呢?

這就須要用到 __name__ 屬性了,這個 ——name—— 屬性值是一個變量,且這個變量是系統給出的。利用這個變量能夠判斷一個模塊是不是主模塊。若是一個屬性的值是 __main__ ,那麼就說明這個模塊是主模塊,反之亦然。可是要注意了: 這個 __main__ 屬性只是幫助咱們判斷是不是主模塊,並非說這個屬性決定他們是不是主模塊,決定是不是主模塊的條件只是這個模塊有沒有被人調用

具體看示例:

首先建立了模塊 lname ,而後判斷一下是不是主模塊,若是是主模塊就輸出 main 不是,就輸出 not main ,首先直接運行該模塊,因爲該模塊是直接使用,而沒有被人調用,因此是主模塊,所以輸出了 main ,具體看下圖:

name屬性區分模塊1
name屬性區分模塊1

而後又建立一個 user_lname 模塊,裏面只是簡單的導入了 lname 模塊,而後執行,輸出的結果是 not main ,由於 lname 模塊被該模塊調用了,因此不是主模塊,輸出結果如圖:

name屬性區分模塊2
name屬性區分模塊2

4、包

包,其實在上面的一些例子中,都建立了不一樣的包名了,具體能夠仔細觀察。在一開始模塊的簡介中提到,使用模塊能夠避免函數名和變量名衝突。相同名字的函數和變量徹底能夠分別存在不一樣的模塊中,所以,咱們本身在編寫模塊時,沒必要考慮名字會與其餘模塊衝突。可是也要注意,儘可能不要與內置函數名字衝突。可是這裏也有個問題,若是不一樣的人編寫的模塊名相同怎麼辦?爲了不模塊名衝突,Python 又引入了按目錄來組織模塊的方法,稱爲包(Package)。

好比最開始的例子,就引入了包,這樣子作就算有相同的模塊名,也不會形成重複,由於包名不一樣,其實也就是路徑不一樣。以下圖,引入了包名後, lname.py 其實變成了 com.Learn.module.nameattributes.lname

Python 包
Python 包

仔細觀察的人,基本會發現,每個包目錄下面都會有一個 __init__.py 的文件,爲何呢?

由於這個文件是必須的,不然,Python 就把這個目錄當成普通目錄,而不是一個包 。 __init__.py 能夠是空文件,也能夠有Python代碼,由於 __init__.py 自己就是一個模塊,而它對應的模塊名就是它的包名。

5、做用域

學習過 Java 的同窗都知道,Java 的類裏面能夠給方法和屬性定義公共的( public )或者是私有的 ( private ),這樣作主要是爲了咱們但願有些函數和屬性能給別人使用或者只能內部使用。 經過學習 Python 中的模塊,其實和 Java 中的類類似,那麼咱們怎麼實如今一個模塊中,有的函數和變量給別人使用,有的函數和變量僅僅在模塊內部使用呢?

在 Python 中,是經過 _ 前綴來實現的。正常的函數和變量名是公開的(public),能夠被直接引用,好比:abc,ni12,PI等;相似__xxx__這樣的變量是特殊變量,能夠被直接引用,可是有特殊用途,好比上面的 __name__ 就是特殊變量,還有 __author__ 也是特殊變量,用來標明做者。注意,咱們本身的變量通常不要用這種變量名;相似 _xxx__xxx 這樣的函數或變量就是非公開的(private),不該該被直接引用,好比 _abc__abc 等;

注意,這裏是說不該該,而不是不能。由於 Python 種並無一種方法能夠徹底限制訪問 private 函數或變量,可是,從編程習慣上不該該引用 private 函數或變量。

好比:

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-

def _diamond_vip(lv):
    print('尊敬的鑽石會員用戶,您好')
    vip_name = 'DiamondVIP' + str(lv)
    return vip_name


def _gold_vip(lv):
    print('尊敬的黃金會員用戶,您好')
    vip_name = 'GoldVIP' + str(lv)
    return vip_name


def vip_lv_name(lv):
    if lv == 1:
        print(_gold_vip(lv))
    elif lv == 2:
        print(_diamond_vip(lv))


vip_lv_name(2)複製代碼

輸出的結果:

尊敬的鑽石會員用戶,您好
DiamondVIP2複製代碼

在這個模塊中,咱們公開 vip_lv_name 方法函數,而其餘內部的邏輯分別在 vip_lv_namevip_lv_name private 函數中實現,由於是內部實現邏輯,調用者根本不須要關心這個函數方法,它只需關心調用 vip_lv_name 的方法函數,因此用 private 是很是有用的代碼封裝和抽象的方法

通常狀況下,外部不須要引用的函數所有定義成 private,只有外部須要引用的函數才定義爲 public。


最後扯淡,歡迎加我微信:androidwed,進入微信Python討論羣,一塊兒學習討論。如今微信羣只有50幾我的.

相關文章
相關標籤/搜索