1. 程式人生 > 程式設計 >如何理解Python中包的引入

如何理解Python中包的引入

Python的from import *和from import *,它們的功能都是將包引入使用,但是它們是怎麼執行的以及為什麼使用這種語法呢?

從一模組匯入全部功能

from import * means意味著“我希望能訪問中我有許可權訪問的全部名稱”。例如以下程式碼something.py:

# something.py
public_variable = 42
_private_variable = 141
def public_function():
 print("I'm a public function! yay!")
def _private_function():
 print("Ain't nobody accessing me from another module...usually")
class PublicClass(object):
 pass
class _WeirdClass(object):
 pass

在Python直譯器中,我們可以執行from something import *,然後看到如下的內容:

>>> from something import *
>>> public_variable
42
>>> _private_variable
...
NameError: name '_private_variable' is not defined
>>> public_function()
"I'm a public function! yay!"
>>> _private_function()
...
NameError: name '_private_function' is not defined
>>> c = PublicClass()
>>> c
<something.publicclass object="" at="" ...="">
>>> c = _WeirdClass()
...
NameError: name '_WeirdClass' is not defined

from something import *從something中匯入了除了以_開頭名稱外的其他所有名稱,按照規範,_開始的名稱是私有的所以未被匯入。

上面沒提到__all__是什麼。__all__是一個字串列表,指定了當from import *被使用時,模組(或者如後文會提到的包)中的哪些符號會被匯出。如果我們不定義__all__(我們在上面的something.py就沒定義),import *預設的匯入方式是匯入除了下劃線(_)開頭的所有名稱。再說一次,程式設計慣例上下劃線表示一個符號是私有的,不匯入是合理的。讓我們來看看在something.py中定義我們自己的__all__會發生什麼。

# something.py
__all__ = ['_private_variable','PublicClass']
# The rest is the same as before
public_variable = 42
_private_variable = 141
def public_function():
 print("I'm a public function! yay!")
def _private_function():
 print("Ain't nobody accessing me from another module...usually")
class PublicClass(object):
 pass
class _WeirdClass(object):
 pass

現在,我們期望from something import *只會匯入_private_variable和PublicClass:

# something.py
__all__ = ['_private_variable','PublicClass']
# The rest is the same as before
public_variable = 42
_private_variable = 141
def public_function():
 print("I'm a public function! yay!")
def _private_function():
 print("Ain't nobody accessing me from another module...usually")
class PublicClass(object):
 pass
class _WeirdClass(object):
 pass

包是怎樣的呢?

當從一個包中匯入全部時,__all__的做法和模組基本一樣,不過它處理的是包中的模組(而不是把模組中的名都匯入)。所以當我們使用from import *.時__all__說明了所有需要被匯入當前名稱空間的模組。

不同之處在於,如果你在一個包的__init__.py裡面沒有宣告__all__,from import *語句不會匯入任何東西(這個說法也不全對,正確的說法在此)

但是,這有什麼不好?

繼續讀之前,在你的Python直譯器中,執行import this,再讀一遍Python之禪(在你孩子每晚睡前也要讀給他們)。

明確比含糊要好。

from import * 是不明確的。它沒告訴我們我們正在匯入什麼或者我們把什麼帶入當前名稱空間了。更好的做法是顯式地匯入我們需要的全部名稱。這種方式下,讀者(非常可能是未來的你自己)就不會困惑於你程式碼中使用的一個變數/方法/類/其他東西是哪兒來的,這也告訴了我們下一點:

可讀性很重要

即使你需要匯入很多東西,一個一個顯式地匯入也更清楚。使用PEP 328:

from Tkinter import (Tk,Frame,Button,Entry,Canvas,Text,LEFT,DISABLED,NORMAL,RIDGE,END)

你現在就能明確知道你的名稱空間裡有什麼,使用ctrl+f能很快地告訴你它們是哪兒來的。

同時,你還總是要承擔模組/包作者更改list內容(加/減東西)的風險。

內容擴充套件:

基本注意點

  • 模組:一般指一個py檔案;包:含有許多py檔案的資料夾,含有 或不含有(Python3中允許)__init__檔案。
  • 凡是在匯入時帶點的,點的左邊都必須是一個包 (import a.fun1 其中a為py檔案)這種匯入形式是錯誤的。
  • 2.from a import fun1 a為一個py檔案,fun1為該檔案的屬性或方法,這種匯入形式是可以的。
  • 一般來說 import 後面不能帶點,如:(from a import b.c是錯誤語法)
  • 匯入模組時,是將模組的py檔案匯入進去(執行);匯入包時,只會執行包中的__init__檔案中的程式碼,故匯入包時一般要匯入到最底層,即from dir1.dir2.dir3 import py檔案或者類、方法、屬性,只有這樣才能找到。但是你可以通過先匯入一個包,然後在包的檔案中的__init__中寫相關的import語句(可以絕對,也可以相對),這樣也可以通過import 包名 的方式將包中的東西匯入進去。

以上就是如何理解Python中包的引入的詳細內容,更多關於Python中包的引入詳解的資料請關注我們其它相關文章!