你知道创建模块都有哪些方式吗?

楔子

导入一个模块,我们一般都会使用 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 的动态性,可以做出任意的骚操作,但是不要太过哦。工作中,故意玩这种操作的话,可能会被批斗。

posted @ 2019-10-31 18:11  古明地盆  阅读(1061)  评论(1编辑  收藏  举报