“鸭子打字”模块的陷阱?

2024-06-26 19:39:49 发布

您现在位置:Python中文网/ 问答频道 /正文

我刚开始尝试一种新的技术,我把它命名为“模块鸭子打字”。

示例:

主模块

import somepackage.req  ## module required by all others
import abc
import Xyz

模块abc

^{pr2}$

在模块abc中,我不需要显式地import req:它可以是包层次结构中的任何地方。当然这需要一些纪律。。。

使用这种技术,可以很容易地在层次结构中重新定位包。

有陷阱在等着我吗?e、 g.迁移到Python 3K

更新了:在更多的测试之后,我决定回到直接在sys.path中插入包依赖项。


Tags: 模块import示例by层次结构requiredallreq
3条回答

我觉得这更像鸭子打字。我还建议使用比“总线”更唯一的标识符

def getBus():
    """ Locates the Bus for this application """
    for mod in sys.modules.values():
        if hasattr(mod, 'Bus') and type(mod.Bus) is...: # check other stuff about mod.Bus
            return mod.Bus
    raise RuntimeError("cannot find Bus")

可能导入了包含“req”的所有类型的模块,但您不知道它是否是您实际要查找的模块:

>>> import urllib.request
>>> import tst
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "tst.py", line 12, in <module>
    Bus=getBus()
  File "tst.py", line 9, in getBus
    return sys.modules[mod_name].__dict__["Bus"]
KeyError: 'Bus'

包的重点是模块层次结构有名称空间。如果用户碰巧导入了某个碰巧包含名称冲突的模块的库,那么“从任何包”中查找模块名称只会导致代码随机中断。在

这种技术很危险而且容易出错。直到有人导入一个新的something.req并得到一个令人困惑的、遥远的错误之前,它都可以与您的测试一起工作。(这是最好的情况;当前的实现将跳转到许多其他模块上。)如果重新构造包,那么在不使用任何魔术的情况下,以自动化的方式修改代码就很容易了。Python使我们可以做各种神奇的、动态的事情,但这并不意味着我们应该这样做。在

相关问题 更多 >