你知道创建模块都有哪些方式吗?
楔子
导入一个模块,我们一般都会使用 import,但除了 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
# 如果想导入子模块,需要一个参数
path = __import__("os.path", fromlist=[""])
print(path) # <module 'ntpath' from 'C:\\python38\\lib\\ntpath.py'>
但平常我们不建议使用这个函数,因为它是专门给解释器用的,我们可以使用一个模块。
import importlib
path = importlib.import_module("os")
print(path) # <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
importlib.machinery 里面提供了三种 Loader,可以直接让我们以打开文件的方式导入一个模块。
from importlib.machinery import (
SourceFileLoader, # 源文件
SourcelessFileLoader, # pyc 文件
ExtensionFileLoader # 扩展文件
)
# 接收两个参数,参数一:给模块起个名字,参数二:文件路径
os = SourceFileLoader("我是 os 模块", r"C:\python38\lib\os.py").load_module()
print(os) # <module '我是 os 模块' from 'C:\\python38\\lib\\os.py'>
至于 pyc 和 pyd 也是类似的,可以自己测试一下。
将一个类的实例变成一个模块
模块在底层也是一个实例对象,那么在 Python 里面我们要如何做呢?
from types import ModuleType
class A(ModuleType):
def __init__(self, name):
super(A, self).__init__(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.xxx) # 获取属性: xxx
a.xxx = "yyy"
print(a.xxx) # yyy
当然啦,我们直接创建一个模块也是可以的。
from types import ModuleType
a = ModuleType("我是 A")
print(a) # <module '我是 A'>
code = """
a = 1
def foo():
return "哼哼"
"""
exec(code, a.__dict__)
print(a.a) # 1
print(a.foo()) # 哼哼
这就是 Python 的动态性,可以做出任意的骚操作,但是不要太过哦。工作中,故意玩这种操作的话,可能会被批斗。
如果觉得文章对您有所帮助,可以请囊中羞涩的作者喝杯柠檬水,万分感谢,愿每一个来到这里的人都生活愉快,幸福美满。
微信赞赏
支付宝赞赏