python3 包的理解


1.什么是包

  包是一種通過使用‘.模塊名’來組織python模塊名稱空間的方式。

       1. 無論是import形式還是from...import形式,凡是在導入語句中(而不是在使用時)遇到帶點的,都要第一時間提高警覺:這是關於包才有的導入語法

       2. 包是目錄級的(文件夾級),文件夾是用來組成py文件(包的本質就是一個包含__init__.py文件的目錄)

       3. import導入文件時,產生名稱空間中的名字來源於文件,import 包,產生的名稱空間的名字同樣來源於文件,即包下的__init__.py,導入包本質就是在導入該文件

強調:

  1. 在python3中,即使包下沒有__init__.py文件,import 包仍然不會報錯,而在python2中,包下一定要有該文件,否則import 包報錯

  2. 創建包的目的不是為了運行,而是被導入使用,記住,包只是模塊的一種形式而已,包即模塊


      包A和包B下有同名模塊也不會沖突,如A.a與B.a來自倆個命名空間

創建目錄:

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/__init__.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)

2.注意事項

1.關於包相關的導入語句也分為import和from ... import ...兩種,但是無論哪種,無論在什么位置,在導入時都必須遵循一個原則:凡是在導入時帶點的,點的左邊都必須是一個包,否則非法。可以帶有一連串的點,如item.subitem.subsubitem,但都必須遵循這個原則。

2.對於導入后,在使用時就沒有這種限制了,點的左邊可以是包,模塊,函數,類(它們都可以用點的方式調用自己的屬性)。

3.對比import item 和from item import name的應用場景:
如果我們想直接使用name那必須使用后者。

3.import

我們在與包glance同級別的文件中測試

import glance.db.models glance.db.models.register_models('mysql') '''結果: from models.py: mysql '''

4.from ... import ...

需要注意的是from后import導入的模塊,必須是明確的一個不能帶點,否則會有語法錯誤,如:from a import b.c是錯誤語法。

我們在與包glance同級別的文件中測試 

from glance.db import models models.register_models('oracle') '''結果: from models.py: oracle '''

from glance.db.models import register_models register_models('mysql') '''結果: from models.py: mysql '''

5.__init__.py文件

  不管是哪種方式,只要是第一次導入包或者是包的任何其他部分,都會依次執行包下的__init__.py文件(我們可以在每個包的文件內都打印一行內容來驗證一下),這個文件可以為空,但是也可以存放一些初始化包的代碼。

 

6.from glance.api import *

  在講模塊時,我們已經討論過了從一個模塊內導入所有*,此處我們研究從一個包導入所有*。

  此處是想從包api中導入所有,實際上該語句只會導入包api下__init__.py文件中定義的名字,我們可以在這個文件中定義__all___:

 

#在__init__.py中定義
x=10

def func(): print('from api.__init.py') __all__=['x','func','policy']

 

       此時我們在於glance同級的文件中執行from glance.api import *就導入__all__中的內容(versions仍然不能導入)。

from glance.api import * versions.create_resource(111) '''結果: NameError: name 'versions' is not defined '''

  目錄結構:

glance/ ├── __init__.py ├── api │ ├── __init__.py   __all__ = ['policy','versions'] │ ├── policy.py │ └── versions.py ├── cmd __all__ = ['manage'] │ ├── __init__.py │ └── manage.py └── db __all__ = ['models'] ├── __init__.py └── models.py from glance.api import * policy.get()

 

7.絕對導入和相對導入

我們的最頂級包glance是寫給別人用的,然后在glance包內部也會有彼此之間互相導入的需求,這時候就有絕對導入和相對導入兩種方式:

絕對導入:以glance作為起始

相對導入:用.或者..的方式最為起始(只能在一個包中使用,不能用於不同目錄內)

例如:我們在glance/api/version.py中想要導入glance/cmd/manage.py

在glance/api/version.py #絕對導入
from glance.cmd import manage manage.main() #相對導入
from ..cmd import manage manage.main()

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM