日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

Python3中__init__.py文件介绍

發布時間:2023/11/27 生活经验 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Python3中__init__.py文件介绍 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

? ? ? Python中的模塊是包含Python定義和語句的文件(A module is a file containing Python definitions and statements)其文件名是模塊名加后綴名.py。在模塊內部,通過全局變量__name__可以獲取模塊名。

? ? ? 模塊包含可執行語句及函數定義。這些語句用于初始化模塊,且僅在import語句第一次遇到模塊名時執行

? ? ? 模塊有自己的私有符號表,用作模塊中所有函數的全局符號表。因此,在模塊內使用全局變量時,不用擔心與用戶定義的全局變量發生沖突。另一方面,可以用與訪問模塊函數一樣的標記法,訪問模塊的全局變量:modname.itemname

? ? ? 可以把其它模塊導入模塊。按慣例,所有import語句都放在模塊(或腳本)開頭,但這不是必須的。導入的模塊名存在導入模塊的全局符號表里。

? ? ? import語句有一個變體,可以直接把模塊里的名稱導入到另一個模塊的符號表,如下:這段代碼不會把模塊名foo導入到局部符號表里

from foo import foo_func, save

? ? ? 還有一種變體可以導入模塊內定義的所有名稱,如下:這種方式會導入所有不以下劃線(_)開頭的名稱。大多數情況下,不要用這種功能,這種方式向解釋器導入了一批未知的名稱,可能會覆蓋已經定義的名稱

from foo import *

? ? ? 注意,一般情況下,不建議從模塊或包導入*,因為,這項操作經常讓代碼變得難以理解。不過,為了在交互式編譯器中少打幾個字,這么用也沒問題。

? ? ? 模塊名后使用as時,直接把as后的名稱與導入模塊綁定,如下:與import foo一樣,這種方式也可以有效地導入模塊,唯一的區別是,導入的名稱是ex_foo

import foo as ex_foo

? ? ? from中也可以使用這種方式,效果類似,如下:

from foo import foo_func as foos

? ? ? 為了保證運行效率,每次解釋器會話只導入一次模塊。如果更改了模塊內容,必須重啟解釋器

? ? ? 以腳本方式執行模塊:這項操作將執行模塊里的代碼,和導入模塊一樣,但會把__name__賦值為”__main__”: python foo.py <arguments>

? ? ? 模塊搜素路徑:導入spam模塊時,解釋器首先查找名為spam的內置模塊。如果沒找到,解釋器再從sys.path變量中的目錄列表里查找spam.py文件。

? ? ? 為了快速加載模塊,Python把模塊的編譯版緩存在__pycache__目錄中,文件名為module.version.pyc,version對編譯文件格式進行編碼,一般是Python的版本號。例如,CPython的3.8發行版中,foo.py的編譯版本(compiled version)緩存為__pycache__/foo.cpython-38.pyc。使用這種命名慣例,可以讓不同Python發行版及不同版本的已編譯模塊共存。Python對比編譯版本與源碼的修改日期,查看它是否已過期,是否要重新編譯,此過程完全自動化。此外,編譯模塊與平臺無關,因此,可在不同架構系統之間共享相同的支持庫。

? ? ? Python在兩種情況下不檢查緩存:(1).從命令行直接載入模塊,只重新編譯,不存儲編譯結果。(2).沒有源模塊,就不會檢查緩存。

? ? ? Python中的包(package)是一種通過使用”點式模塊名(dotted module names)”來構建Python模塊命名空間的方法。例如,模塊名A.B表示包A中名為B的子模塊。導入包時,Python搜索sys.path里的目錄,查找包的子目錄。

? ? ? Python只把含__init__.py文件的目錄當成包(Python3.2之后的版本不需要再額外的去專門創建一個__init__.py文件)。最簡情況下,__init__.py只是一個空文件,但該文件也可以執行包的初始化代碼,或設置__all__變量。當import指定的包時,此包內的__init__.py會被隱性執行,且只執行一次。

? ? ? 注意:使用from package import item時,item可以是包的子模塊(或子包),也可以是包中定義的函數、類或變量等其它名稱。import語句首先測試包中是否定義了item;如果未在包中定義,則假定item是模塊,并嘗試加載。如果找不到item,則觸發ImportError異常。相反,使用import item.subitem.subsubitem句法時,除最后一項外,每個item都必須是包;最后一項可以是模塊或包,但不能是上一項中定義的類、函數或變量。

? ? ? import語句使用如下慣例:

? ? ? (1).如果包的__init__.py代碼定義了列表__all__,運行from package import *時,它就是用于導入的模塊名列表。發布包的新版本時,包的作者應更新此列表。即如果顯式聲明了__all__,import *就只會導入__all__列出的成員,如果__all__定義有誤,會拋出異常。

? ? ? (2).如果沒有定義__all__,from package.subpackage import *語句不會把包package.subpackage中所有子模塊都導入到當前命名空間;該語句只確保導入包package.subpackage(可能還會運行__init__.py中的初始化代碼),然后再導入包中定義的名稱。這些名稱包括__init__.py中定義的任何名稱(以及顯式加載的子模塊),還包括之前import語句顯式加載的包里的子模塊。

? ? ? 包中含有多個子包時,可以使用絕對導入引用兄弟包中的子模塊。還可以用import語句的from module import name形式執行相對導入。這些導入語句使用前導句點表示相對導入中的當前包(.)和父包(..),如下:

from . import echo
from .. import formats

? ? ? Python包有多種結構。每個.py文件可作為單個模塊。__init__.py文件定義方式如下,也可以使用不同方式的組合:

? ? ? 第一種方式:from .module import *

? ? ? 優點:

? ? ? (1).用戶不需要知道模塊名稱,例如,哪個功能在哪個模塊中,他們只需要包名和函數名。

? ? ? (2).導入頂級包(import top-level package)后,用戶可以訪問任何功能。

? ? ? (3).制表符(Tab-completion)會補全為你提供的所有內容。

? ? ? (4).當模塊添加新特性時,不需要更新任何導入語句,它們將自動被包含。

? ? ? 缺點:

? ? ? (1).要求所有函數和類必須命名唯一,即在模塊中不能含有相同名字的函數。在模塊中若含有相同名字的函數,雖然可能不會報錯,但是調用的函數可能未必是你希望的那個。

? ? ? (2).如果包很大,它會向命名空間添加很多內容,并且會減慢速度。

? ? ? (3).對于有些函數防止用戶調用的話,還需要作單獨處理,如使用下劃線來防止函數導入。

? ? ? 建議:

? ? ? (1).在難以預測用戶的工作流程時使用。

? ? ? (2).當用戶可能經常在不同模塊之間來回切換時使用。

? ? ? (3).當用戶僅與幾個模塊(a few modules)一起使用。如果有很多模塊,新用戶可能更難在文檔中找到他們想要的功能。

? ? ? (4).在可能頻繁添加或刪除對象(object)時使用。

? ? ? 第二種方式:from .module import func 或 from .module import func1, func2

? ? ? 優點:

? ? ? (1).擁有第一種方式的所有優點,并更容易控制哪些對象可供用戶使用。

? ? ? 缺點:

? ? ? (1).如果有許多模塊,并且每個模塊中有許多函數,那么__init__.py中內容會變得非常混亂。

? ? ? (2).當向模塊中添加新類或函數時,它們也必須顯式添加到__init__.py文件中。

? ? ? 建議:

? ? ? (1).當你的模塊由單個類組成時特別有用。

? ? ? (2).當你有少量對象要導入時使用。

? ? ? (3).當你的對象具有明確名稱時使用。

? ? ? (4).當你確切地知道你的用戶需要哪些對象以及他們不需要哪些對象時使用。

? ? ? (5).當你不希望頻繁添加大量需要導入的新模塊和對象時使用。

? ? ? 第三種方式:import package.module

? ? ? 優點:

? ? ? (1).簡化了__init__.py文件,僅在添加新的模塊時才需要更新。

? ? ? (2).它是靈活的,它可用于僅導入用戶需要的內容或導入所有內容。

? ? ? (3).使用別名可以清理長的package.module規范(例如, import matplotlib.pyplot as plt)。

? ? ? (4).可以有多個同名對象(例如,foo和bar模塊中都調用了save()的函數)。

? ? ? 缺點:

? ? ? (1).一些導入方法會使代碼閱讀起來更復雜,例如,foo.foo_func()不指示foo來自哪個包。

? ? ? (2).最易讀的方法(import test_package,沒有別名)可能會導致長代碼塊(例如, test_package.foo.foo_func())使事情變得混亂。

? ? ? (3).用戶很難找到所有可能的功能。

? ? ? 建議:

? ? ? (1).當你有一系列復雜的模塊時使用,其中大多數用戶永遠不需要。

? ? ? (2).import test_package導入大量對象時使用,可能會很慢。

? ? ? (3).當你可以為不同類型的用戶定義非常清晰的工作流程時使用。

? ? ? (4).當你期望用戶能夠很好地瀏覽你的文檔時使用。

? ? ? 第四種方式:使用__all__

? ? ? 注:以上內容及以下測試代碼主要來自于:

? ? ? 1.?https://towardsdatascience.com/whats-init-for-me-d70a312da583

? ? ? 2.?https://docs.python.org/zh-cn/3/tutorial/modules.html

? ? ? 測試代碼組織結構如下:頂層目錄有一個test_package_main.py文件和一個test_package目錄,test_package目錄下有4個.py文件,各個文件內容如下:

? ? ? test_package_main.py:

import sysvar = 4if var == 1: # 第一種方式,導入模塊中所有內容import test_packagetest_package.foo_func()test_package.bar_func()test_package.baz_func()test_package.save() # 不能確定調用的是bar.py中的是還是foo.py中的. 由__init__.py決定,會調用后import的#test_package._calc() # AttributeError: module 'test_package' has no attribute '_calc'
elif var == 2: # 第二種方式,指定模塊中要導入的內容,同一模塊中若導入多個函數,中間用逗號分割: from .module import func1, func2import test_packagetest_package.foo_func()test_package.bar_func()test_package.baz_func()
elif var == 3: # 第三種方式# 用戶可以采用三種不同的使用方法method = 3if method == 1:import test_packagetest_package.foo.foo_func()test_package.bar.bar_func()test_package.baz.baz_func()elif method == 2:from test_package import foo, bar, baz # 從包中導入子模塊foo.foo_func()bar.bar_func()baz.baz_func()elif method == 3:import test_package.foo as ex_foo # 從包中導入單個模塊import test_package.bar as ex_barimport test_package.baz as ex_bazex_foo.foo_func()ex_bar.bar_func()ex_baz.baz_func()ex_foo.save()ex_bar.save()print("csdn addr:", ex_foo.csdn_addr)print("sys path:", sys.path)print("dir:", dir(ex_foo)) # dir為內置函數,獲取指定模塊的方法列表,包括變量、函數等等
elif var == 4: # 使用__all__from test_package import * # import * 就只會導入__all__列出的成員foo.foo_func()bar.bar_func()#baz.baz_func() # NameError: name 'baz' is not defined

? ? ? test_package/foo.py:

def foo_func():print("this is a foo function")def save():print("this is a foo save function")def _calc():print("this is a foo _calc function")github_addr = "https://github.com/fengbingchun"
csdn_addr = "https://blog.csdn.net/fengbingchun"

? ? ? test_package/bar.py:

def bar_func():print("this is a bar function")def save():print("this is a bar save function")def _calc():print("this is a bar _calc function")

? ? ? test_package/baz.py:

def baz_func():print("this is a baz function")

? ? ? test_package/__init__.py:

# reference: https://towardsdatascience.com/whats-init-for-me-d70a312da583var = 4print("import package: test_package")if var == 1: # 第一種方式,導入模塊中所有內容# from .module import *from .foo import *from .bar import *from .baz import *
elif var == 2: # 第二種方式,指定模塊中要導入的內容,同一模塊中若導入多個函數,中間用逗號分割: from .module import func1, func2# from .module import funcfrom .foo import foo_funcfrom .bar import bar_funcfrom .baz import baz_func
elif var == 3: # 第三種方式import test_package.fooimport test_package.barimport test_package.baz
elif var == 4: # 使用__all____all__ = ["foo", "bar"]

? ? ? GitHub:https://github.com/fengbingchun/Python_Test

總結

以上是生活随笔為你收集整理的Python3中__init__.py文件介绍的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。