<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
匯入一個模組,我們一般都會使用 import 關鍵字,但有些場景下 import 難以滿足我們的需要。所以除了 import 之外還有很多其它匯入模組的方式,下面就來介紹一下。
這是一個內建函數,直譯器在 import 的時候,實際上就執行了這個函數。
# import os 等價於如下方式 os = __import__("os") print(os) # <module 'os' from 'C:\python38\lib\os.py'> # 但是這種方式不能多級匯入 path = __import__("os.path") print(path) # <module 'os' from 'C:\python38\lib\os.py'> # 可以看到,匯入的仍是 os,而不是 os.path # 如果想匯入子模組,需要一個引數 fromlist # 我們給它傳一個非空列表即可 path = __import__("os.path", fromlist=[""]) print(path) # <module 'ntpath' from 'C:\python38\lib\ntpath.py'>
但是官方不建議使用這個函數,因為它是專門給直譯器用的,我們可以使用一個模組。
import importlib os = importlib.import_module("os") print(os) # <module 'os' from 'C:\python38\lib\os.py'> # 可以多級匯入 path = importlib.import_module("os.path") print(path) # <module 'ntpath' from 'C:\python38\lib\ntpath.py'>
所以當匯入的模組名以字串的形式存在時,或者模組名不符合規範時,就可以使用這種方式。
importlib.machinery 裡面提供了三種 Loader,可以讓我們以開啟檔案的方式匯入一個模組。
from importlib.machinery import ( SourceFileLoader, # 匯入原始檔 SourcelessFileLoader, # 匯入 pyc 檔案 ExtensionFileLoader # 匯入擴充套件檔案 ) # 引數一:給模組起個名字 # 引數二:檔案路徑 os = SourceFileLoader( "我是 os 模組", r"C:python38libos.py" ).load_module() print(os) """ <module '我是 os 模組' from 'C:\python38\lib\os.py'> """ print(os.path.join("video", "overwatch", "hanzo.mp4")) """ videooverwatchhanzo.mp4 """ # 我們看到結果一切正常,但有一點需要注意 # 如果是匯入包的話,那麼要匯入包裡面的 __init__.py 檔案 pd = SourceFileLoader( "我是 pandas 模組", r"C:python38libsite-packagespandas__init__.py" ).load_module() print(pd.DataFrame({"a": [1, 2, 3], "b": [4, 5, 6]})) """ a b 0 1 4 1 2 5 2 3 6 """ # 如果只寫到 pandas,那麼會丟擲 PermissionError # 因為我們不能把目錄當成檔案來讀取 # 至於 import 一個包,本質上也是載入包內部的 __init__.py # 但這裡需要我們顯式地加上 __init__.py
同理載入 pyc 和 pyd 也是類似的,但需要注意的是,載入普通檔案和 pyc 檔案時,我們可以隨便起名字,也就是第一個引數任意。但對於 pyd 檔案,第一個引數必須和 pyd 檔案的名字保持一致。
Python 一切皆物件,模組自然也不例外。既然是物件,那麼必然就會有相應的類來範例化它。
import os import hashlib import numpy # os.__class__ 等價於 type(os) print(os.__class__) # <class 'module'> print(hashlib.__class__) # <class 'module'> print(numpy.__class__) # <class 'module'>
在 Python 裡面,我們一般會把單獨的可匯入檔案稱之為模組,把包含多個模組的目錄稱之為包。通過模組和包,我們可以對專案進行功能上的劃分,分門別類地進行組織。
但不管是模組、還是包,它們都是 module 這個類的範例物件,列印結果也能說明這一點。所以從直譯器的角度來看的話,模組和包區分的並沒有那麼明顯,直接把包看做是包內部的 __init__.py 即可。
既然模組的型別是 class module,那麼我們是不是也可以通過呼叫型別物件的方式建立呢?顯然是可以的,但是 module 這個類直譯器沒有暴露給我們,直接用的話會提示變數 module 未定義。所以只能先隨便匯入一個模組,然後通過 type 函數或者 __class__ 屬性獲取。
# 不過 types 模組內部已經幫我們做好了 # ModuleType = type(sys) from types import ModuleType print(ModuleType) # <class 'module'> # 類物件有了,下面就可以建立了 # module 類接收兩個引數 # 引數一:模組的名字,必須傳遞 # 引數二:模組的 doc,不傳預設為 None satori = ModuleType("古明地覺", "模組的名字是一個女孩,她來自地靈殿") print(satori) # <module '古明地覺'> print(satori.__doc__) # 模組的名字是一個女孩,她來自地靈殿 # 但此時模組裡面是沒啥東西的,我們加一些屬性吧 # 操作模組本質上是在操作它的屬性字典 code = """ age = 16 def foo(): return "^_^" """ # 執行 code,結果會體現在 satori 的屬性字典中 exec(code, satori.__dict__) print(satori.age) # 16 print(satori.foo()) # ^_^
需要注意的是裡面 exec 函數,它會把字串當成程式碼來執行,所以這就要求字串的來源必須是可靠的,我們能夠確保不會出現惡意內容。而如果是使用者傳遞的字串,那麼絕不能用 exec 來執行,當然 eval 也是同理。
然後是 exec 的第二個引數,表示執行時的名稱空間,預設是全域性名稱空間。所以當不指定第二個引數時,exec(code) 相當於建立了兩個全域性變數:age 和 foo。
code = """ age = 16 def foo(): return "^_^" """ exec(code) print(age) # 16 print(foo()) # ^_^
但是我們在執行的時候,將它換成了 satori.__dict__,所以結果相當於給模組新增了兩個變數,或者說屬性。
如果想將一個類的範例變成模組,那麼這個類應該繼承 ModuleType。
import sys from types import ModuleType class A(ModuleType): def __init__(self, module_name): super().__init__(module_name) def __getattr__(self, item): return f"不存在的屬性: {item}" def __setattr__(self, key, value): self.__dict__[key] = value def __str__(self): return f"<module '{self.__name__}' from '我來自於虛無'>" a = A("我是 A") print(a) # <module '我是 A' from '我來自於虛無'> print(a.__name__) # 我是 A print(a.xx) # 不存在的屬性: xx a.xx = "xx" print(a.xx) # xx # 加入到 sys.modules 中 sys.modules["嘿嘿"] = a import 嘿嘿 print(嘿嘿.xx) # xx print(嘿嘿.yy) # 不存在的屬性: yy
是不是很好玩呢?
以上就是載入模組的幾種方式,主要用途如下:
到此這篇關於Python實現建立模組的方法詳解的文章就介紹到這了,更多相關Python建立模組內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45