python3 包的理解

1.什麼是包

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

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

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

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

強調:oracle

  1. 在python3中,即便包下沒有__init__.py文件,import 包仍然不會報錯,而在python2中,包下必定要有該文件,不然import 包報錯app

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


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

建立目錄:spa

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)

目錄結構:code

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()
相關文章
相關標籤/搜索