一丶模塊我們經常說模塊模塊的,究竟什么是模塊呢?一個模塊就是包含了定義和聲明的文件,文件名就是模塊名字加上.py的后綴但其實加載的模塊分為四個通用類別:1.使用編寫的代碼(.py文件)2.已被編譯為共享庫或DLL的C或C++擴展3.包好一組模塊的包4.使用C編寫并鏈接到解釋器的內置模塊導入的過程中發生了什么事兒?1.找到要被導入的模塊2.判斷這個模塊是否被導入過3.如果這個模塊沒被導入創建一個屬于這個模塊的命名空間執行這個文件找到你要導入的變量給你要導入的變量創建一個引用,指向你要導入的變量自定義模塊:.py,文件名.py,模塊名
import sys
print(sys.modules) #導入的模塊會寫在這里面
sys.path.append(my_module) #將my_module模塊寫入里面
import my_module #導入my_module模塊
print(my_module.name) #調用my_module中的name
復制
為模塊起別名
# 給模塊起別名
import my_moudle as m
m.read1
#給模塊起別名,起了別名之后,使用這個模塊就都使用別名引用變量了
復制
導入多個模塊
#導入多個模塊
import os,time
import os as o,time as t
# 規范建議:先導入內置模塊,再導入擴展(第三方)模塊,再導入自定義模塊
復制
from..
from my_module import read1
def read1():
print('in my read1')
from my_module import read2
read1()
復制
需要特別強調的一點是:中的變量賦值不是一種存儲操作空間自定義模塊沒了,而只是一種綁定關系,如下:
from my_module import money,read1
money=100 #將當前位置的名字money綁定到了100
print(money) #打印當前的名字
read1() #讀取my_module.py中的名字money,仍然為1000
'''
from the my_module.py
my_module->read1->money 1000
'''
復制
*
from my_module import * #將模塊my_module中所有的名字都導入到當前名稱空間
print(money)
print(read1)
print(read2)
print(change)
'''
執行結果:
from the my_module.py
'''
復制
能約束*導入的變量的內容
__all__ = ['name','read1','read2']
from my_module import *
print(name)
read1()
read2()
復制
把模塊當做腳本執行 當一個py文件當做一個腳本的時候:能夠獨立的提供一個功能,能自主完成交互當成一個模塊的時候,能夠被導入這個調用這個功能,不能自主交互我們可以通過模塊的全局變量來查看模塊名:當做腳本運行:等于''當做模塊導入:=模塊名作用:用來控制.py文件在不同的應用場景下執行不同的邏輯 ==''
def fib(n):
a, b = 0, 1
while b < n:
print(b, end=' ')
a, b = b, a+b
print()
if __name__ == "__main__":
print(__name__)
num = input('num :')
fib(int(num))
復制
模塊搜索路徑 解釋器在啟動時會自動加載一些模塊,可以使用sys.查看在第一次導入某個模塊時(比如),會先檢查該模塊是否已經被加載到內存中,如果有則直接引用,如果沒有,解釋器則會查找同名的內建模塊,如果還沒有找到就送sys.path給出的目錄列表中依次尋找.py文件所以總結模塊的查找順序是:內存中已經加載的模塊->內置模塊->sys.path路徑中包含的模塊
import sys
import calculate
print(sys.path)
path = r'D:\Learn\day21\模塊的循環引用'
sys.path.append(path)
復制
編譯文件 1.如果是在命令中被直接導入模塊,則按照這種方式,每次導入都會重新編譯,并且不會存儲編譯后的結果2.如果源文件不存在,那么緩存的結果也不會被使用,如果想在沒有源文件的情況下來使用編譯后的結果,則編譯后的結果必須在源目錄下dir()函數內建函數dir是用來查找模塊中定義的名字,返回一個有序字符串列表.如果沒有參數,dir()列舉出當前定義的名字
import my_module
dir(my_module)
復制
二丶包
1.無論是形式還是from...形式,凡是在導入語句中(而不是在使用時)遇到帶點的,都要第一時間提高警覺:這是關于包才有的導入語法
2.包是目錄級的(文件夾級),文件夾是用來組成py文件(包的本質就是一個包含.py文件的目錄)
3.導入文件時,產生名稱空間中的名字來源于文件,包,產生的名稱空間的名字同樣來源于文件,即包下的.py,導入包的本質就是在導入該文件
強調:
1.在中,即使包下沒有.py文件,包仍然不會報錯,而在中,包下一定要有該文件,否則包報錯
2.創建包的目的不是為了運行,而是被導入使用,記住,包只是模式的一種形式而已,包即模塊
import os
os.makedirs('glance/api')
os.makedirs('glance/cmd')
os.makedirs('glance/db')
l = []
l.append(open('glance/__init__.py','w'))
l.append(open('glance/api/__init__.py','w'))
l.append(open('glance/api/policy.py','w'))
l.append(open('glance/api/versions.py','w'))
l.append(open('glance/cmd/__init__.py','w'))
l.append(open('glance/cmd/manage.py','w'))
l.append(open('glance/db/models.py','w'))
map(lambda f:f.close() ,l)
復制
創建目錄代碼
glance/ #Top-level package
├── __init__.py #Initialize the glance package
├── api #Subpackage for api
│ ├── __init__.py
│ ├── policy.py
│ └── versions.py
├── cmd #Subpackage for cmd
│ ├── __init__.py
│ └── manage.py
└── db #Subpackage for db
├── __init__.py
└── models.py
復制
目錄結構
#文件內容
#policy.py
def get():
print('from policy.py')
#versions.py
def create_resource(conf):
print('from version.py: ',conf)
#manage.py
def main():
print('from manage.py')
#models.py
def register_models(engine):
print('from models.py: ',engine)
復制
文件內容
在導入包時必須遵守一個原則:凡是在導入時帶點的,點的左邊都必須是一個包
from..
需要注意的是from后導入的模塊,必須是明確的一個不能帶點,否則會有語法錯誤
from glance.db import models
models.register_models('mysql')
from glance.db.models import register_models
register_models('mysql')
復制
import glance.db.models
glance.db.models.register_models('mysql')
復制
.py文件不管是哪種方式,只要是第一次導入包或者包的任何其他部分,都會依次執行包下的.py文件,這個文件可以為空,但是也可以存在一些初始化包的代碼. *此處是想從包api中導所有,實際上該語句只會導入包api下.py文件中定義的名字,我們可以在這個文件中定義:
#在__init__.py中定義
x=10
def func():
print('from api.__init.py')
__all__=['x','func','policy']
復制
絕對導入和相對導入
絕對導入:以作為起始
相對導入:用.或者..的方式最為起始(只能在一個包中使用,不能用于不同的目錄內)
例如:我們在/api/.py中想要導入/cmd/.py
在glance/api/version.py
#絕對導入
from glance.cmd import manage
manage.main()
#相對導入
from ..cmd import manage
manage.main()
復制
特別需要注意的是:可以用導入內置或者第三方模塊(已經在sys.path中),但是要絕對避免使用來導入自定義包的子模塊(沒有在sys.path中)空間自定義模塊沒了,應該使用from... ...的絕對或者相對導入,且包的相對導入只能用from的形式。
絕對導入:
glance/
├── __init__.py from glance import api
from glance import cmd
from glance import db
├── api
│ ├── __init__.py from glance.api import policy
from glance.api import versions
│ ├── policy.py
│ └── versions.py
├── cmd from glance.cmd import manage
│ ├── __init__.py
│ └── manage.py
└── db from glance.db import models
├── __init__.py
└── models.py
絕對導入
復制
絕對導入
相對導入:
glance/
├── __init__.py from . import api #.表示當前目錄
from . import cmd
from . import db
├── api
│ ├── __init__.py from . import policy
from . import versions
│ ├── policy.py
│ └── versions.py
├── cmd from . import manage
│ ├── __init__.py
│ └── manage.py from ..api import policy
#..表示上一級目錄,想再manage中使用policy中的方法就需要回到上一級glance目錄往下找api包,從api導入policy
└── db from . import models
├── __init__.py
└── models.py
相對導入
復制
相對導入
單獨導入包 單獨導入包名稱時不會導入包中所有包含的所有子模塊,如:
#在與glance同級的test.py中
import glance
glance.cmd.manage.main()
'''
執行結果:
AttributeError: module 'glance' has no attribute 'cmd'
'''
復制
解決方法:
#glance/__init__.py
from . import cmd
#glance/cmd/__init__.py
from . import manage
復制
執行:
#在于glance同級的test.py中
import glance
glance.cmd.manage.main()
復制
之后直接調用模塊中的方法
glance/
├── __init__.py from .api import *
from .cmd import *
from .db import *
├── api
│ ├── __init__.py __all__ = ['policy','versions']
│ ├── policy.py
│ └── versions.py
├── cmd __all__ = ['manage']
│ ├── __init__.py
│ └── manage.py
└── db __all__ = ['models']
├── __init__.py
└── models.py
import glance
policy.get()
import glance
復制
View Code
軟件開發規范