20. 企業級開發基礎1:自定義模組

大牧莫邪發表於2017-05-22

本節內容

1 模組的概念和意義
2 模組的定義和使用
3 再說變數的作用域

之前的課程中,我們已經瞭解了python程式設計開發的基礎部分內容 包含了資料型別、變數、運算子、程式選擇結構、迴圈結構、函式處理、字串處理等等內容。 本節內容開始,我們開始學習python企業級開發基礎部分的內容,會涉及到模組式整合開發、物件導向程式設計、錯誤的除錯和測試、高階開發[檔案IO處理,網路程式設計,多執行緒程式開發、正規表示式等等]內容,

1. 模組的概念和意義

我們在常規程式開發的過程中,如果只是通過python來寫一些專案維護的小指令碼程式,前面學過的內容已經基本夠用了,但是如果涉及到企業級開發的複雜的一些需求的話,程式設計開發過程中會出現大量的程式碼,如果著大量的程式碼(如:1萬行程式碼)寫在一個python檔案中,就會讓這個檔案的體積非常的龐大,開發過程中會造成大量的不必要的問題:如變數定義是否會覆蓋其他定義的變數,新增功能處理程式碼會否影響其他的功能,由於大量程式碼集中在一個檔案中導致修改維護變得非常的不容易,程式碼的可讀性非常 差等等各種問題。

此時,為了方便我們將不同的處理功能區分開,我們將處理不同資料或者功能的函式分別分組存放在不同的python檔案中,就會將上面一個比較龐大的python檔案拆分成多個python檔案,每個python檔案中的程式碼內容會比較少,通過多個Python檔案互相組合的方式來完成複雜的處理功能。這樣拆分的不同的python檔案,每個python檔案就是一個單獨的python模組,專業術語:module 我們定義好的Python模組,可以在需要的地方,通過import 模組名稱關鍵字來引入這個模組,程式碼如下: ```

user.py 使用者模組
--------------
def showInfo(name, age):
      print("user info:  name[" + name + "] age [" + age + "]")
--------------
goods.py 商品模組
--------------
def showGoods(name, price):
      print("goods info: goodsName: [" + name + "] price [¥" + str(price)+ "]")
--------------
main.py 主模組中使用其他的模組
--------------
import user
import goods

user.showInfo("tom", 18)
goods.showGoods("alienware", 14999)

```

拆分模組的好處是第一、將一個比較複雜的單檔案拆分成多個檔案,方便程式碼的管理和開發維護,第二、我們開發並完善好的Python模組,在其他需要這個模組功能的地方就可以直接引入組合這個模組,不需要重複編寫Python程式碼了,第三、不同的python模組中,就可以使用相同名稱的變數了,不同模組中的變數不會互相覆蓋資料或者產生衝突,降低了我們程式碼開發的成本

2. 模組的使用和解決的問題

拆分模組之後,我們會遇到這樣的問題

2.1. 變數名稱衝突

變數名稱在不同的python檔案/模組中,同名變數不會互相產生衝突 ```

user.py 使用者模組
--------------
# 記錄當前系統中使用者數量的變數count
count = 12
# 列印當前系統中使用者數量的函式
def getCount():
      print("user count:" + str(count))
--------------
goods.py 商品模組
--------------
# 記錄當前系統中商品數量的變數count
count = 1001
# 獲取並答應當前系統中所有商品數量的函式
def getCount():
      print("goods count:" + str(count))
--------------
main.py 主模組中使用其他的模組
--------------
import user
import goods
user.getCount()  #執行結果:12
goods.getCount() # 執行結果:1001

```

2.2. 模組名稱衝突

我們也同樣考慮到了,模組名稱和定義變數一樣,某些情況下模組名稱也有可能衝突,如:我們的專案中處理使用者資料定義了一個工具模組utils.py,處理商品資料定義了一個工具模組utils.py,此時這兩個模組衝突了;解決方案如下 我們會將不同的模組,python定義了包的概念,根據處理的功能或者資料的不同,存放在不同的包中,用於區分不同的模組; 包在python中,就是一個資料夾,為了區分包資料夾和普通的資料夾,在包資料夾中,必須定義一個__init__.py模組檔案,這個檔案內容可以為空。 ```

# 1. 建立users資料夾,是用來處理使用者資料的包
# 2. 在users資料夾下建立__init__.py檔案,內容可以為空
# 3. 在users資料夾下建立utils.py工具模組
--------------
"這是處理使用者資料的工具模組"
x = 129.00
y = 432.24
# 獲取使用者當前位置的函式
def getLocation():
      # 返回使用者位置資料
      return x, y
--------------
#4. 建立goods資料夾,是用來處理使用者資料的包
#5. 在goods資料夾下建立__init__.py檔案,內容可以為空
#6. 在goods資料夾下建立utils.py工具模組
--------------
"這是處理商品資料的工具模組"
address = "河南鄭州"
# 獲取商品產地的函式
def getProduction():
      # 返回商品的產地
      return address

--------------
7.建立main.py程式執行的入口檔案,引入users和goods兩個模組
使用不同模組中的函式
--------------
import users.utils
import goods.utils
xx, yy = users.utils.getLocation()
addr = goods.utils.getProduction()
print(xx, yy)
print(addr)

``` 20. 企業級開發基礎1:自定義模組模組開發" />

3. 模組中再說變數

變數在之前的課程中,我們已經提到了變數在Python中有區域性變數和全域性變數的區分,是通過是否定義在函式內部來區分的。 此時有了多模組之後,對於變數的作用域,需要進行更加細緻的劃分。

3.1. 模組內部

模組內部,還是按照正常的情況進行劃分,按照是否定義在函式內部來區分全域性變數和區域性變數,在模組檔案內部,變數的使用沒有任何的變數 在模組內部,變數依舊是全域性變數/區域性變數,變數的作用域正常使用即可 ```

"這是一個使用者資料處理模組"
# 全域性變數,記錄系統中使用者的線上人數
onlineCount = 100

def getUserinfo(name):
      # 定義了一個區域性變數,這個區域性變數只能在當前函式內部訪問
      msg = "尊敬的使用者您好,"
      if name == "":
            name = "遊客"
      return msg + name;

```

3.2. 不同模組之間的變數訪問

python中定義了模組之後,不同模組之間訪問資料和函式的情況就比較常見了;模組中的變數,有些是需要讓別的模組訪問的,有些是不希望別的模組訪問的,此時就會將變數區分為模組公開的變數、模組私有的變數兩種變數了。

  • python的模組中,按照正常的命名規則命名的變數或者函式,規範為公開的變數或者函式,其他的模組都可以正常的訪問

  • python的模組中,使用一個下劃線開頭來命名的變數或者函式,規範為私有的變數或者函式,只能在當前模組中使用

  • python的模組中,使用兩個下劃線開頭的變數,可以別模組直接引用使用具有特殊的含義,如__name__表示當前模組名稱等等;規範要求我們自己的變數名稱儘量不要使用這樣的名稱。

```

"商品資訊管理模組goods.py"
# 遊客打折折扣,變數名稱下劃線開頭,不希望其他模組訪問
_discountVisitor = 9.5
# 會員打折折扣,變數名稱下劃線開頭,不希望其他模組訪問
_discountMember = 8.5

# 遊客購買折扣計算,函式名稱下劃線開頭,不希望其他模組訪問
def _visitorBuy(goodsName, price):
    resPrice = price * _discountVisitor;
    print("尊敬的遊客,您購買了" + name + ",總價格是:" + str(resPrice));

# 會員購買折扣計算,函式名稱下劃線開頭,不希望其他模組訪問
def _memberBuy(goodsName, price):
    resPrice = price * _discountMember;
    print("尊敬的遊客,您購買了" + name + ",總價格是:" + str(resPrice));

# 購買商品的函式,允許其他模組訪問的函式,正常命名
def buy(type, name, price):
    if type == 1:
        _visitorBuy(name, price)
    elif type == 2:
        _memberBuy(name, price);
    else:
        print("對不起,您沒有許可權購買商品")

```

注意:這裡出現了公開/公有變數和私有變數/函式的概念,公開/公有變數/函式就是我們平時定義的普通的全域性變數/函式;這裡的私有變數/函式,是在原有的全域性變數/函式的基礎上,變數名稱前面加了一個下劃線,約定這是私有的變數/函式,不應該讓其他的模組訪問【記住:這裡的約定,不是強制,所以其他模組如果要訪問這樣的私有變數,還是可以訪問到的,但是規範上不應該這麼做】 ```

"使用者資訊處理模組users.py"
# 這裡定義了一個私有的變數 _userType和_userDesc
_userType = "管理員"
_userDesc = "遊客操作許可權,只能訪問不能修改任何資訊"
def _changeDisc(_userType):
    if _userType == "管理員":
        _userDesc = "超級管理員操作許可權"
    if _userType == "會員":
        _userDesc = "普通操作許可權,不能修改敏感資訊"
-------------------------
"程式執行的主要模組main.py"
import users
# 使用users模組中的_userType變數
print(users._userType)
users._userType = "會員"
print(users._userType)
# * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
#  上面的程式碼中,我們可以在main模組中,訪問引入的
# 另一個模組users模組中定義的私有變數_userType
# !這不是我們想要的,私有的不是不能讓其他模組訪問嗎?
# !這裡請注意:下劃線開頭的變數,規範是私有變數,不應該
# 讓其他的模組訪問,而不是強制,這裡的規範是一種專案開發約定!
# * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

```

相關文章