1. 程式人生 > >python進階之py文件內置屬性

python進階之py文件內置屬性

手動 定義 時也 修改 以及 oba xxx 賦值 默認

前言

對於任何一個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__

該屬性不是模塊默認的,需要手動定義,它的功能有二:

  1. 記錄一個模塊有哪些重要的、對外開發的類、方法或變量等,或記錄一個包哪些對外開放的模塊;

  2. 限制導入,當使用“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__函數返回的是一個變量,代表一個模塊,所有後續方法的調用都要在這個變量的基礎上。

總結

  1. 對於眾多的模塊屬性,python最常用的是__name__,__doc__,__author__,__all__.

  2. 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文件內置屬性