淺析python中特殊文件和特殊函數

導入模塊

模塊通常為單獨的.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特殊文件和特殊函數內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: