首頁 > 軟體

淺析python中特殊檔案和特殊函數

2022-02-24 19:01:51

匯入模組

模組通常為單獨的.py檔案,可以用import直接參照,可以作為模組的檔案型別有.py、.pyo、.pyc、.pyd、.so、.dll在匯入模組時,直譯器做以下工作:

  • 已匯入模組的名稱建立新的名稱空間,通過該名稱空間就可以存取匯入模組的屬性和方法。
  • 在新建立的名稱空間中執行原始碼檔案。
  • 建立一個名為原始碼檔案的物件,該物件參照模組的名稱空間,這樣就可以通過這個物件存取模組中的函數及變數

import 語句可以在程式的任何位置使用,你可以在程式中多次匯入同一個模組,但模組中的程式碼僅僅在該模組被首次匯入時執行。後面的import語句只是簡單的建立一個到模組名稱空間的參照而已。sys.modules字典中儲存著所有被匯入模組的模組名到模組物件的對映。

匯入包

多個相關聯的模組組成一個包,即多個.py檔案構成一個包,以便於維護和使用,同時能有限的避免名稱空間的衝突。一般來說,包的結構可以是這樣的:

package
  |- subpackage1
      |- __init__.py
      |- a.py
  |- subpackage2
      |- __init__.py
      |- b.py

有以下幾種匯入方式

import subpackage1.a # 將模組subpackage.a匯入全域性名稱空間,例如存取a中屬性時用subpackage1.a.attr
from subpackage1 import a # 將模組a匯入全域性名稱空間,例如存取a中屬性時用a.attr_a
from subpackage1.a import attr_a # 將模組a的屬性直接匯入到名稱空間中,例如存取a中屬性時直接用attr_a

使用from語句可以把模組直接匯入當前名稱空間,from語句並不參照匯入物件的名稱空間,而是將被匯入物件直接引入當前名稱空間

可以被import語句匯入的物件是以下型別:

  • 模組檔案(.py檔案)
  • C或C++擴充套件(已編譯為共用庫或DLL檔案)
  • 包(包含多個模組)
  • 內建模組(使用C編寫並已連結到Python直譯器中)

特殊檔案

1、__init__.py檔案

__init__.py檔案的作用就是將該檔案所處的資料夾當做一個模組來管理,每當有外部檔案來import的時候,就會執行裡面的函數

__init__.py是怎麼工作的

當一個目錄下含有這個檔案,則這個資料夾就是一個python模組,通常__init__.py檔案為空,但是我們還可以為它增加其他的功能。我們在匯入一個包時,實際上是匯入了它的__init__.py檔案。這樣我們可以在__init__.py檔案中批次匯入我們所需要的模組,而不再需要一個一個的匯入。

當import匯入該模組時,同時會執行該檔案內容,當匯入該模組中的某個函數時需要加上該包名,不然就會報錯,如下,當在其他檔案中要匯入子包subpackage_1中的test11函數時,需要加上包名mypackage

from mypackage.subpackage_1 import test11

__init__.py中還有一個重要的變數,__all__, 它用來將模組全部匯入。

# __init__.py
__all__ = ['os', 'sys', 're', 'urllib']
# a.py
from package import *

這時就會把註冊在__init__.py檔案中__all__列表中的模組和包匯入到當前檔案中來。在瞭解了__init__.py的工作原理後,應該能理解該檔案就是一個正常的python程式碼檔案。因此可以將初始化程式碼放入該檔案中。

2、.pyc與 .pyo檔案

.py檔案在組合時,會生成.pyc檔案,在組合時,會將.py檔案中的import的檔案連結起來組合成位元組碼寫到一個.pyc檔案中,後面執行時,就直接執行.pyc檔案,省去每次都要重新組合,提高執行速度,(當.py檔案的修改時間發生改變,這樣會生成新的.pyc檔案)在直譯器使用-O選項時,將使用同名的.pyo檔案,這個檔案去掉了斷言(assert)、斷行號以及其他偵錯資訊,體積更小,執行更快。(使用-OO選項,生成的.pyo檔案會忽略檔案資訊)

特殊函數

1、建構函式

建構函式是一種特殊的類成員方法,主要用在建立物件時初始化物件
python中的建構函式用__init__命名

2、解構函式

解構函式是建構函式的反函數,在銷燬物件時呼叫他們,往往用來做清理善後,
例如:資料庫連線物件可以在解構函式中釋放對資料庫範例資源的佔用
python中為類定義解構函式的方法是在類中定義一個名為__del__的沒有返回值和引數的函數
python中顯示銷燬物件的方法,使用del關鍵

3、靜態函數和類函數

python中支援兩種基於類名存取成員函數:靜態函數和類函數
不同點:類函數有一個隱形引數cls可以用來獲取類資訊
靜態函數使用裝飾器@staicmethod定義
類函數使用裝飾器@classmethod定義

4、以下劃線開頭的函數

  • 單前導下劃線:_var
  • 單末尾下劃線:var_
  • 雙前導下劃線:__var
  • 雙前導和末尾下劃線:__var__
  • 單下劃線:_

單線劃:_var

下劃線字首的含義是告知其他程式設計師:以單個下劃線開頭的變數或方法僅供內部使用。 該約定在PEP 8中有定義。這不是Python強制規定的。 Python不像Java那樣在“私有”和“公共”變數之間有很強的區別。

如果使用萬用字元從模組中匯入所有名稱,則Python不會匯入帶有前導下劃線的名稱(除非模組定義了覆蓋此行為的__all__列表)

# This is my_module.py:

def external_func():
   return 23
def _internal_func():
   return 42
>>> from my_module import *
>>> external_func()
23
>>> _internal_func()
NameError: "name '_internal_func' is not defined"

與萬用字元匯入不同,常規匯入不受前導單個下劃線命名約定的影響:

>>> import my_module
>>> my_module.external_func()
23
>>> my_module._internal_func()
42

單末尾下劃線 var_

有時候,一個變數的最合適的名稱已經被一個關鍵字所佔用。 因此,像class或def這樣的名稱不能用作Python中的變數名稱。 在這種情況下,你可以附加一個下劃線來解決命名衝突,總之,單個末尾下劃線(字尾)是一個約定,用來避免與Python關鍵字產生命名衝突。 PEP 8解釋了這個約定。

雙前導下劃線:__var

到目前為止,我們所涉及的所有命名模式的含義,來自於已達成共識的約定。 而對於以雙下劃線開頭的Python類的屬性(包括變數和方法),情況就有點不同了。雙下劃線字首會導致Python直譯器重寫屬性名稱,以避免子類中的命名衝突。這也叫做名稱修飾(name mangling) — 直譯器會更改變數的名稱,以便在類被擴充套件的時候不容易產生衝突。對於該屬性的呼叫可以通過方法呼叫,而不能直接呼叫該屬性,類似實現屬性的私有,例如:

class ManglingTest:
   def __init__(self):
       self.__mangled = 'hello'
   def get_mangled(self):
       return self.__mangled
>>> ManglingTest().get_mangled() # 通過方法獲取該函數的值
'hello'
>>> ManglingTest().__mangled # 直接呼叫該屬性時會報錯
AttributeError: "'ManglingTest' object has no attribute '__mangled'"

但我們依然可以通過特殊方法來直接獲取該屬性的值,即通過(_類名__屬性)的方式獲取,例如

>>> ManglingTest()._ManglingTest__mangled
'hello'

所以在python中並沒有真正的私有變數,python直譯器會自動將__var修飾為: _類名__屬性,該特性對於以雙下劃線開頭的方法依然適用

class MangledMethod:
   def __method(self):
       return 42
   def call_it(self):
   	  return self.__method()
>>> MangledMethod().__method() # 直接呼叫該方法會報錯
AttributeError: "'MangledMethod' object has no attribute '__method'"
>>> MangledMethod().call_it()
42
>>> MangledMethod()._MangledMethod__method() # 通過該形式也是可以呼叫該方法
42

雙前導和雙末尾下劃線 var

如果一個名字同時以雙下劃線開始和結束,則不會應用名稱修飾。不同於僅有雙下滑線開頭的變數或函, 由雙下劃線字首和後雙下滑線包圍的變數不會被Python直譯器修改,但是,Python保留了有雙前導和雙末尾下劃線的名稱,用於特殊用途。 這樣的例子有,__init__(物件建構函式),或__call__(該函數是使得一個物件可以被呼叫)最好避免在自己的程式中使用以雙下劃線開頭和結尾的名稱,以避免與將來Python語言的變化產生衝突。

單下劃線

按照習慣,有時候單個獨立下劃線是用作一個名字,來表示某個變數是臨時的或無關緊要的。

例如,在下面的迴圈中,我們不需要存取正在執行的索引,我們可以使用“_”來表示它只是一個臨時值:

>>> for _ in range(32):
...    print('Hello, World.')
>>> car = ('red', 'auto', 12, 3812.4)
>>> color, _, _, mileage = car
>>> color
'red'
>>> mileage
3812.4
>>> _
12

到此這篇關於python中特殊檔案和特殊函數的文章就介紹到這了,更多相關python特殊檔案和特殊函數內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com