python中的模块原则_python 的模块与包
一 模塊
1、什么是模塊
? 模塊是一系列功能的結合體
?分為三大類:
?1、內置的模塊
?2、第三方的模塊
?3、自定義的模塊
?一個 python 文件本身就是一個模塊,文件名:m.py 模塊名:m
ps:模塊分為四種形式
?1 使用python編寫的.py文件
2 已被編譯為共享庫或DLL的C或C++擴展
3 把一系列模塊組織到一起的文件夾(注:文件夾下有一個__init__.py文件,該文件夾稱之為包)
4 使用C編寫并鏈接到python解釋器的內置模塊
2、為何要用模塊
1、內置與第三方的模塊拿來就用,無需定義,這種拿來主義,可以極大地提升自己的開發效率
2、自定義模塊,可以將程序的各部分功能提取出來放到一模塊中為大家共享使用
?好處:減少代碼冗余,程序組織結構更加清晰
3、如何使用模塊
1 導入模塊
首次導入模塊會發生的事情
import foo
1、產生 foo.py 的名稱空間, 將 foo.py運行過程中產生的名字都丟到 foo 的名稱空間中
2、執行 foo.py
3、在當前文件中產生的有一個名字 foo,該名字指向 1 中產生的名稱空間
具體如下圖:
之后的導入,都是直接引用首次導入產生的 foo.py名稱空間,不會重復執行代碼
import foo
import foo
import foo
2 引用
具體:
print(foo.x)
print(foo.get)
print(foo.charge)
強調1:模塊名.名字,是指名道姓地問某一個模塊要名字對應的值,不會與當前名稱空間中的名字發生沖突
x=1111111111111
print(x)
print(foo.x)
強調 2:無論是查看還是修改,操作的都是模塊本身,與調用位置無關
import foo
x=3333333333
# foo.get()
foo.change()
print(x)
可以以逗號為分隔符在一行導入多個模塊
import time, foo, m
3、導入模塊的規范(順序)
?1、內置模塊
?2、第三方模塊
?3、程序員自定義模塊
模塊是第一類對象
imoport foo
自定義模塊的命名應該采用純小寫 + 下劃線的風格
可以在函數內導入模塊
def func():
import foo
4、 py 文件的用途
?一個 py 文件有兩種用途
?1)被當做程序運行
?2)被當做模塊導入
1、執行 py 文件與導入文件的區別是什么?
?執行 py 文件:
?1)在內存中產生名稱空間
?2)運行 py 文件
?3)將運行 py 文件產生的名字放到名稱空間內
?名稱空間會在文件運行結束后回收
?導入文件:
?1)產生模塊文件的內存空間
?2)運行模塊
?3)在該文件名稱空間內產生模塊字并指向模塊文件的名稱空間
2、from...import.....
?1、產生一個模塊的名稱空間
?2、運行 foo.py 將運行過程中產生的名字都丟到模塊的名稱空間去
?3、在當前名稱空間拿到一個名字,該名字指向模塊名稱空間 中的某一個內存地址
from foo import x #x = 模塊foo中的值1的內存地址
from foo improt change
from foo import get
x = 111 #重新將 x 賦值 指向新的內存地址
?優點:代碼更精簡,導入后在使用時不需要加前綴
?缺點: 容易與當前名稱空間混淆
一行導入多個名字(不推薦)
from foo import x,get,change
導入模塊中所有名字(不推薦)
from foo import *
了解:
__ all __:在模塊中默認存的是模塊中所有名字,所以在其它地方能通過 from foo import * 導入所有的名字
__ all__ =['login', 'get'] #控制*代表的名字有哪些
起別名
from foo improt x as xx
3、循壞導入問題
循環導入問題指的是在一個模塊加載/導入的過程中導入另外一個模塊,而在另外一個模塊中又返回來調用第一個模塊中名字,由于第一個模塊尚未加載完畢,所以引用失敗,拋出異常。原因是:在 python 中,同一個模塊只會在第一次導入時執行其內部代碼,再次導入該模塊時,即便是該模塊尚未完全加載完畢也不會重復執行內部代碼。
具體案列:
m1.py
print('正在導入m1')
from m2 import y
x = 'm1'
m2.py
print('正在導入m2')
from m1 import x
y = 'm2'
run.py
import m1
#1、執行run.py會拋出異常
正在導入m1
正在導入m2
Traceback (most recent call last):
File "/Users/linhaifeng/PycharmProjects/pro01/1 aaaa練習目錄/aa.py", line 1, in
import m1
File "/Users/linhaifeng/PycharmProjects/pro01/1 aaaa練習目錄/m1.py", line 2, in
from m2 import y
File "/Users/linhaifeng/PycharmProjects/pro01/1 aaaa練習目錄/m2.py", line 2, in
from m1 import x
ImportError: cannot import name 'x'
#2、分析
先執行run.py--->執行import m1,開始導入m1并運行其內部代碼--->打印內容"正在導入m1"
--->執行from m2 import y 開始導入m2并運行其內部代碼--->打印內容“正在導入m2”--->執行from m1 import x,由于m1已經被導入過了,所以不會重新導入,所以直接去m1中拿x,然而x此時并沒有存在于m1中,所以報錯
解決方案
方案一:
?將導入模塊放到最后,保證在導入時,所有名字都已經加載過
# 文件:m1.py
print('正在導入m1')
x='m1'
from m2 import y
# 文件:m2.py
print('正在導入m2')
y='m2'
from m1 import x
# 文件:run.py內容如下,執行該文件,可以正常使用
import m1
print(m1.x)
print(m1.y)
方案二:
導入語句放到函數中,只有調用函數才會執行其內部代碼
# 文件:m1.py
print('正在導入m1')
def f1():
from m2 import y
print(x,y)
x = 'm1'
# 文件:m2.py
print('正在導入m2')
def f2():
from m1 import x
print(x,y)
y = 'm2'
# 文件:run.py內容如下,執行該文件,可以正常使用
import m1
m1.f1()
注:循壞導入問題大多數情況下是因為程序設計失誤導致的,在編寫程序時應該盡量避免出現循環/嵌套導入。如果多個模塊都需要共享某些數據,可以將共享的數據集中存放到某一個地方。
4、搜索模塊的路徑與優先級
?無論import 還是 from...impor在導入模塊時都涉及到查找問題
優先級:
?1、內存(內置模塊)
?2、硬盤:按照 sys.path中存放的文件的順序依次查找要導入的模塊
# mmm.py #它是代碼文件夾下的py 文件
import sys
print(sys.path)
#環境變量路徑
['/Users/tophan/Desktop/代碼', '/Users/tophan/Desktop/代碼', '/Applications/PyCharm.app/Contents/helpers/pycharm_display', '/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', '/Users/tophan/Library/Python/3.6/lib/python/site-packages', '/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages', '/Applications/PyCharm.app/Contents/helpers/pycharm_matplotlib_backend']
1、列表中的每一個元素都可以看做一個文件目錄
2、列表中第一個目錄為執行文件的路徑
3、第二個目錄為整個項目的路徑
當第一次導入模塊時,如果被導入模塊與執行文件在同一目錄下是肯定可以正常導入的,如果不在同一目錄下,就涉遍歷查找該模塊的存放目錄是否在環境變量路徑中。為了確保模塊對應的源文件在任何地方都可以被找到,需要將源文件所在的路徑添加到 sys.path中。
#sys.append(模塊源文件的路徑)
sys.path.append(r'/pythoner/projects/') #也可以使用sys.path.insert(……)
import foo #無論foo.py在何處,都可以導入它
5、區分py文件
區分一個 py 文件是執行文件還是導入文件
print(__name__)
1、當 py 文件被運行時,__name__的值為'__mian__'
2、當 py 文件被當做模塊導入時,__name__的值為模塊名
if __ name__ == '__main__':
print('文件被執行')
get()
change()
else:
#被當做模塊導入時做的事情
print('文件被導入')
二 包
1、包就是一個包含有__ init __ .py文件的文件夾
?包的本質是模塊的一種形式,包是用來被當做模塊導入,導入包其實其實是導入包下的__ init __文件
在python3中,即使包下沒有__init__.py文件,import 包仍然不會報錯,而在python2中,包下一定要有該文件,否則import 包報錯
創建包的目的不是為了運行,而是被導入使用,包只是模塊的一種形式而已,包的本質就是一種模塊
導入包會發生的事情:
?1、產生一個名稱空間
?2、運行包下的__ init __.py 文件,將運行過程中產生的名字都 丟到 1(模塊)產生的名稱空間中
?3、在當前執行文件的名稱空間中拿到一個名字,這個名字指向 1 (模塊)的名稱空間
import mmm
print(mmm.x)
print(mmm.y)
mmm.say()
環境變量是以執行文件為準的,所有被導入的模塊或者說后續的其他文件引用的 sys.path都是參照執行文件的 sys.path
也就是說,一個項目在執行文件運行時,項目中其他的文件的模塊或包被導入和引用時都是去執行文件的 sys.path查找的,被導入模塊中有 sys.path.append('路徑'),在執行文件運行時,被導入的模塊會將路徑添加到環境變量列表中。
#模塊:mmm
print('運行了。。。。')
import sys
sys.path.append('/11111111111')
#執行文件
import sys
import mmm
sys.path.append('/aaaaaaaaaaaaaaaaaaaaaaaaaa')
print(sys.path)
結果展示:
運行了。。。。
['/Users/tophan/Desktop/代碼', '/Users/tophan/Desktop/代碼', '/Applications/PyCharm.app/Contents/helpers/pycharm_display', '/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', '/Users/tophan/Library/Python/3.6/lib/python/site-packages', '/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages', '/Applications/PyCharm.app/Contents/helpers/pycharm_matplotlib_backend', '/11111111111', '/aaaaaaaaaaaaaaaaaaaaaaaaaa']
#被導入模塊中有 sys.path.append('路徑'),在執行文件運行時,被導入的模塊會將路徑添加到環境變量列表中。
2 導入包 和 模塊遵循原則
1、凡是在導入時帶點的,點的左邊都必須是一個包,否則非法。
2、可以帶有一連串的點,如import 頂級包.子包.子模塊,但都必須遵循這個原則。但對于導入后,在使用時就沒有這種限制了,點的左邊可以是包,模塊,函數,類(它們都可以用點的方式調用自己的屬性)。
from a.b.c.d.e.f import xxx
import a.b.c.d.e.f
#其中a、b、c、d、e 都必須是包
導入包:
1、包A和包B下有同名模塊也不會沖突,如A.a與B.a來自倆個命名空間
2、import 導入文件時,產生名稱空間中的名字來源文件
?import 包,產生的名稱空間的名字同樣來源于文件,即包下的__ init __ .py , 導入包本質就是導入該文件。
3、導入包的兩種方式
1、絕對導入
?絕對導入,以包的文件夾作為起始來進行導入
import sys
from foo.m3 import f3
2、相對導入
?相對導入:僅限于包內使用,不能跨出包(包內模塊之間的導入,推薦使用相對導入)
?. :代碼當前文件夾
?.. : 代表上一層文件夾
#目錄
foo--|
bbb
|
m1
|
m2
|
foo1
# 在foo1執行文件中
from .m1 import f1
from .m2 import f2
from .bbb.m4 import f4
強調:
?1、相對導入不能跨出包,所以相對導入僅限于包內模板彼此之間應用
?2、絕對導入時沒有任何限制的,所以絕對導入是一種通用的導入方式
補充:
在pycharm中導入自己寫的模塊時,得不到智能提示,并在模塊名下出現下紅線,但是代碼可以執行,錯誤提示為下圖所示:
原因:出現 以上情況,是因為文件目錄設置的問題,pycharm中的最上層文件夾是項目文件夾,在項目中導包默認是從這個目錄下尋找,當在其中再次建立目錄,目錄內的py文件如果要導入當前目錄內的其他文件,單純的使用import導入,是得不到智能提示的,這是pycharm設置的問題,并非導入錯誤。
解決方法:
?從根目錄下導入時,就會有提示信息
from ATM.lib.common import logger
總結
以上是生活随笔為你收集整理的python中的模块原则_python 的模块与包的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 达内python人工智能19年大纲_20
- 下一篇: 微服务架构设计模式 pdf_六种常用的微