python進階之py文件內置屬性
前言
對於任何一個python文件來說,當python解釋器運行一個py文件,會自動將一些內容加載到內置的屬性中;一個模塊我們可以看做是一個比類更大的對象。
查看模塊的內置屬性
我們先創建一個典型的py文件
# test.py # -*- coding: utf-8 -*- """ some doc """ import os var1 = None class Person(object): pass if __name__ == "__main__": print(dir()) # [‘Person‘, ‘__annotations__‘, ‘__builtins__‘, ‘__cached__‘, ‘__doc__‘, ‘__file__‘, ‘__loader__‘, ‘__name__‘, ‘__package__‘, ‘__spec__‘, ‘os‘, ‘var1‘]
通過dir()方法我們可以獲取到該模塊的所有的顯式或隱式的屬性或方法;可看到隱式的屬性有__annotations__,__builtins__,__cached__,__annotations__,__doc__,__file__,__loader__,__name__;
我們打印一下每個魔法屬性:
print(__name__) # __main__ print(__annotations__) # {} print(__builtins__) # <module ‘builtins‘ (built-in)> print(__cached__) # None print(__doc__) # some doc print(__file__) # .../test.py print(__loader__) # <_frozen_importlib_external.SourceFileLoader object at 0x000002398E831F28> print(__package__) # None print(__spec__) # None # 其中__name__、__doc__、__file__、__package__是可以直接使用的,其它的內置屬性一般不允許直接使用。
內置魔法屬性
- __name__
該屬性代表當前模塊的名字,每個py文件默認的屬性,如果當前模塊是主程序,值為“__main__”,如果不是主程序,值為模塊名。這個屬性經常用來區分主程序和作為被導入模塊的程序。
- __builtins__
該屬性代表內置模塊builtins,即所有的內建函數、內置類型、內置異常等;在python執行一個py文件時,會將內置模塊賦值給這個屬性;如果不是主程序,那麽這個屬性是一個builtins模塊所有方法的字典。
- __doc__
模塊的說明文檔,py文件初始化時,將文件開始的說明字符串賦值給這個屬性。
- __file__
該屬性代表文件的絕對路徑,任何一個模塊使用這個屬性就可獲得本模塊的絕對路徑;但是該屬性只在windows環境下可用,在linux環境下不可用。
- __cached__
緩存文件,如果是主程序,那麽該屬性為None,其他模塊的該屬性指向該模塊的pyc字節文件,這樣在py文件不發生修改的情況下可以減少編譯的時間,更快地加載上下文環境。
- __annotations__
該屬性對於模塊文件來說,沒有開放給用戶使用;但對於函數來說,這個方法用來記錄參數的類型和返回值。
def get_sum(x,y):
return x + y
print(get_sum.__annotations__) # {}
def get_sum(x, y: int) -> int:
return x + y
print(get_sum.__annotations__) # {‘y‘: <class ‘int‘>, ‘return‘: <class ‘int‘>}
函數的參數和返回值如果在定義的時候指定了類型,那麽它們就會以鍵值對的形式記錄到函數的__annotations__屬性中,但對於匿名函數來說,這個屬性是不存在的。
- __loader__
該屬性py3.3之前沒有,引用了本模塊的加載器對象,即該模塊的上下文是由這個加載器加載到內存中的。
- __package__
該屬性是一個文件是否是包的標誌,在主程序中該屬性的值永遠是None,不要使用它;當一個包被導入到主程序中,該包的__package__屬性為包的名字。
# test
--__init__.py
# main.py
import test
print(test.__package__) # test
- __spec__
該屬性記錄一個模塊的詳細信息,是一個ModuleSpec對象,
其他魔法屬性
- __author__
該屬性用來定義模塊的作者信息,可以是字符串,也可以是列表、字典等數據結構。
# test.py
__author__ = {‘auth‘:‘tianyuzhiyou‘;‘bg‘:‘https://www.cnblogs.com/cwp-bg/‘}
- __all__
該屬性不是模塊默認的,需要手動定義,它的功能有二:
記錄一個模塊有哪些重要的、對外開發的類、方法或變量等,或記錄一個包哪些對外開放的模塊;
限制導入,當使用“from xxx import *”形式導入時,實際導入的只有__all__屬性中的同名的對象而不是所有,但對於“from xxx import xxx”指定了具體的名字則all屬性被忽略。
魔法方法
- __import__
該魔法方法是import觸發,即import os 相當於os = __import__(‘os‘),也可以直接使用,主要用於模塊延遲加載,或重載模塊。
- 參數:
name:模塊的名字;
global:包含全局變量的字典,采用默認值 global()
local:包含局部變量的字典,采用默認值 local()
fromlist:被導入的子模塊的名稱
level:指定使用絕對導入還是相對導入,0表示只執行絕對導入。
- 實例
# 設有文件目錄
testx
--__init__.py
--name.py
--test
--__init__.py
--name.py
t = __import__(‘testx‘,fromlist=[‘name‘,‘test2‘]) # 導入testx包以及包內的name、test2模塊
print(t.name) # t變量代表testx包,如果name不再fromlist中則不可用
t = __import__(‘testx.test2‘, fromlist=[‘name‘]) # 導入testx包的子包
print(t.name) # 代表testx.test2.name
__import__函數返回的是一個變量,代表一個模塊,所有後續方法的調用都要在這個變量的基礎上。
總結
對於眾多的模塊屬性,python最常用的是__name__,__doc__,__author__,__all__.
python在執行import語句時,調用__import__方法,同時也做了對被導入模塊的一些初始化工作,如:將被導入模塊的名字賦值給被導入模塊__name__,將被導入模塊的絕對路徑賦值給被導入模塊__file__,將builtins模塊的globals()賦值給被導入模塊__builtins__,將被導入模塊的說明賦值給被導入模塊的_doc_,將被導入模塊的編譯字節文件路徑賦值給被導入模塊__cached__,創建一個ModuleSpec對象賦值給被導入模塊的__spec__,如果被導入的是包,將包的名字賦值__package__屬性.
參考
https://www.jb51.net/article/128957.htm
https://docs.python.org/3/
python進階之py文件內置屬性