Python實現(xiàn)創(chuàng)建模塊得方法詳解

目錄

楔子

導(dǎo)入一個模塊,我們一般都會使用 import 關(guān)鍵字,但有些場景下 import 難以滿足我們得需要。所以除了 import 之外還有很多其它導(dǎo)入模塊得方式,下面就來介紹一下。

__import__

這是一個內(nèi)置函數(shù),解釋器在 import 得時候,實際上就執(zhí)行了這個函數(shù)。

#?import?os?等價于如下方式os?=?__import__("os")print(os)??#?<module?'os'?from?'C:\python38\lib\os.py'>#?但是這種方式不能多級導(dǎo)入path?=?__import__("os.path")print(path)??#?<module?'os'?from?'C:\python38\lib\os.py'>#?可以看到,導(dǎo)入得仍是?os,而不是 os.path#?如果想導(dǎo)入子模塊,需要一個參數(shù)?fromlist#?我們給它傳一個非空列表即可path?=?__import__("os.path",?fromlist=[""])print(path)??#?<module?'ntpath'?from?'C:\python38\lib\ntpath.py'>

但是官方不建議使用這個函數(shù),因為它是專門給解釋器用得,我們可以使用一個模塊。

import?importlibos?=?importlib.import_module("os")print(os)??#?<module?'os'?from?'C:\python38\lib\os.py'>#?可以多級導(dǎo)入path?=?importlib.import_module("os.path")print(path)??#?<module?'ntpath'?from?'C:\python38\lib\ntpath.py'>

所以當(dāng)導(dǎo)入得模塊名以字符串得形式存在時,或者模塊名不符合規(guī)范時,就可以使用這種方式。

importlib.machinery

importlib.machinery 里面提供了三種 Loader,可以讓我們以打開文件得方式導(dǎo)入一個模塊。

from?importlib.machinery?import?(????SourceFileLoader,??#?導(dǎo)入源文件????SourcelessFileLoader,??#?導(dǎo)入 pyc?文件????ExtensionFileLoader??#?導(dǎo)入擴展文件)#?參數(shù)一:給模塊起個名字#?參數(shù)二:文件路徑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"""#?我們看到結(jié)果一切正常,但有一點需要注意#?如果是導(dǎo)入包得話,那么要導(dǎo)入包里面得?__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??b0??1??41??2??52??3??6"""#?如果只寫到?pandas,那么會拋出?PermissionError#?因為我們不能把目錄當(dāng)成文件來讀取#?至于?import?一個包,本質(zhì)上也是加載包內(nèi)部得?__init__.py?#?但這里需要我們顯式地加上?__init__.py

同理加載 pyc 和 pyd 也是類似得,但需要注意得是,加載普通文件和 pyc 文件時,我們可以隨便起名字,也就是第一個參數(shù)任意。但對于 pyd 文件,第一個參數(shù)必須和 pyd 文件得名字保持一致。

通過 module 類創(chuàng)建模塊

Python 一切皆對象,模塊自然也不例外。既然是對象,那么必然就會有相應(yīng)得類來實例化它。

import?osimport?hashlibimport?numpy#?os.__class__?等價于?type(os)print(os.__class__)??#?<class?'module'>print(hashlib.__class__)??#?<class?'module'>print(numpy.__class__)??#?<class?'module'>

在 Python 里面,我們一般會把單獨得可導(dǎo)入文件稱之為模塊,把包含多個模塊得目錄稱之為。通過模塊和包,我們可以對項目進行功能上得劃分,分門別類地進行組織。

但不管是模塊、還是包,它們都是 module 這個類得實例對象,打印結(jié)果也能說明這一點。所以從解釋器得角度來看得話,模塊和包區(qū)分得并沒有那么明顯,直接把包看做是包內(nèi)部得 __init__.py 即可。

既然模塊得類型是 class module,那么我們是不是也可以通過調(diào)用類型對象得方式創(chuàng)建呢?顯然是可以得,但是 module 這個類解釋器沒有暴露給我們,直接用得話會提示變量 module 未定義。所以只能先隨便導(dǎo)入一個模塊,然后通過 type 函數(shù)或者 __class__ 屬性獲取。

#?不過?types?模塊內(nèi)部已經(jīng)幫我們做好了#?ModuleType?=?type(sys)from?types?import?ModuleTypeprint(ModuleType)??#?<class?'module'>#?類對象有了,下面就可以創(chuàng)建了#?module?類接收兩個參數(shù)#?參數(shù)一:模塊得名字,必須傳遞#?參數(shù)二:模塊得 doc,不傳默認為 Nonesatori?=?ModuleType("古明地覺",?"模塊得名字是一個女孩,她來自地靈殿")print(satori)??#?<module?'古明地覺'>print(satori.__doc__)??#?模塊得名字是一個女孩,她來自地靈殿#?但此時模塊里面是沒啥東西得,我們加一些屬性吧#?操作模塊本質(zhì)上是在操作它得屬性字典code?=?"""age?=?16def?foo():????return?"^_^""""#?執(zhí)行?code,結(jié)果會體現(xiàn)在?satori?得屬性字典中exec(code,?satori.__dict__)print(satori.age)??#?16print(satori.foo())??#?^_^

需要注意得是里面 exec 函數(shù),它會把字符串當(dāng)成代碼來執(zhí)行,所以這就要求字符串得來源必須是可靠得,我們能夠確保不會出現(xiàn)惡意內(nèi)容。而如果是用戶傳遞得字符串,那么絕不能用 exec 來執(zhí)行,當(dāng)然 eval 也是同理。

然后是 exec 得第二個參數(shù),表示執(zhí)行時得名字空間,默認是全局名字空間。所以當(dāng)不指定第二個參數(shù)時,exec(code) 相當(dāng)于創(chuàng)建了兩個全局變量:age 和 foo。

code?=?"""age?=?16def?foo():????return?"^_^""""exec(code)print(age)??#?16print(foo())??#?^_^

但是我們在執(zhí)行得時候,將它換成了 satori.__dict__,所以結(jié)果相當(dāng)于給模塊添加了兩個變量,或者說屬性。

將一個類得實例變成一個模塊

如果想將一個類得實例變成模塊,那么這個類應(yīng)該繼承 ModuleType。

import?sysfrom?types?import?ModuleTypeclass?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__)??#?我是?Aprint(a.xx)??#?不存在得屬性:?xxa.xx?=?"xx"print(a.xx)??#?xx#?加入到?sys.modules?中sys.modules["嘿嘿"]?=?aimport?嘿嘿print(嘿嘿.xx)??#?xxprint(嘿嘿.yy)??#?不存在得屬性:?yy

是不是很好玩呢?

小結(jié)

以上就是加載模塊得幾種方式,主要用途如下:

  • 導(dǎo)入一個在 sys.path 中得模塊,并且模塊名已知,那么直接使用 import 關(guān)鍵字即可;
  • 導(dǎo)入一個在 sys.path 中得模塊,但模塊名是運行時得一個字符串,那么使用 importlib 模塊得 import_module 函數(shù);
  • 導(dǎo)入一個不在 sys.path 中得模塊,使用 importlib.machinery 得各種 Loader,只要把模塊得路徑傳進去即可。當(dāng)然啦,位于 sys.path 中得模塊也可以使用該方法,但顯然此時使用前兩種更為方便;
  • 直接創(chuàng)建一個模塊,通過繼承 module 類來實現(xiàn),并且還可以加入到 sys.modules 中。Python 有一個第三方模塊叫 sh,顧名思義是用來執(zhí)行 Linux Shell 命令得,它內(nèi)部就使用了繼承 module 類來創(chuàng)建模塊得這種方式。但是要知道 module 這個類解釋器沒有暴露給我們,我們需要通過 type(模塊) 或者 模塊.__class__ 得方式獲取;

到此這篇關(guān)于Python實現(xiàn)創(chuàng)建模塊得方法詳解得內(nèi)容就介紹到這了,更多相關(guān)Python創(chuàng)建模塊內(nèi)容請搜索之家以前得內(nèi)容或繼續(xù)瀏覽下面得相關(guān)內(nèi)容希望大家以后多多支持之家!

聲明:所有內(nèi)容來自互聯(lián)網(wǎng)搜索結(jié)果,不保證100%準(zhǔn)確性,僅供參考。如若本站內(nèi)容侵犯了原著者的合法權(quán)益,可聯(lián)系我們進行處理。
發(fā)表評論
更多 網(wǎng)友評論1 條評論)
暫無評論

返回頂部

主站蜘蛛池模板: 日韩一级黄色片| 蜜臀精品无码av在线播放| 波多野结衣在线免费电影| 天天天天躁天天爱天天碰2018| 十九岁日本电影免费完整版观看 | 亚洲变态另类一区二区三区| 99热综合在线| 激情亚洲综合网| 在我跨下的英语老师景老师 | 亚洲区小说区图片区qvod| 404款禁用软件onlyyou| 欧美牲交a欧美牲交aⅴ图片| 国产高清在线a视频大全| 亚洲欧洲自拍拍偷综合| 2021国产麻豆剧果冻传媒影视| 欧美日韩亚洲国内综合网香蕉| 国产精品第一区第27页| 亚洲人成伊人成综合网久久久| 在线免费观看h| 最近中文字幕电影大全免费版| 国产成人综合美国十次| 久久亚洲国产欧洲精品一| 色婷婷精品视频| 久久精品一本到99热免费| 男操女视频网站| 免费成人在线电影| 久久免费观看国产精品| 草莓视频污污在线观看| 新97人人模人人爽人人喊| 制服丝袜一区二区三区| chinese帅哥18kt| 波多野结衣免费一区视频| 国产精品单位女同事在线| 久久精品麻豆日日躁夜夜躁| 贱妇汤如丽全篇小说| 忘忧草日本在线播放www| 亚洲精品视频在线观看免费| 18男同少爷ktv飞机视频| 日韩欧美高清色码| 啊轻点灬大ji巴黑人太粗| av无码免费看|