【问题标题】:How to parameterize a generic Python module?如何参数化通用 Python 模块?
【发布时间】:2012-09-13 13:06:39
【问题描述】:

我可以创建一个使用模块进口商提供的功能的模块吗?

我想编写通用代码而不指定几个关键功能的实现。我希望用户指定这些。我可以将这些作为所有函数的输入,但这看起来很难看。

如果我正在编写一个对象,我会创建一个抽象类。模块有等价物吗?

编辑:我特别询问如何使用模块中的函数而不是类中的方法来做到这一点。

【问题讨论】:

  • 当您说您希望用户指定函数时,您是希望他们这样做一次并在程序期间使用这些函数,还是根据上下文动态使用不同的函数你的动态模块是从哪里调用的?
  • 为什么你特别想用模块中的函数来做这个?对于您的用例,使用类而不是模块似乎要容易得多。

标签: python generics module abstract


【解决方案1】:

可以在运行时对模块进行猴子修补并向模块添加新功能。

import my_module
def my_implementation():
    pass

my_module.implementation = my_implementation

然而,这在 Python 社区中是不受欢迎的。它本质上是不稳定的,因为这会影响该模块的所有用户。例如,如果您使用的另一个模块也使用了您已猴子修补的模块,则您的其他模块可能会显示难以调试的不稳定行为。

对于你想做的事情,你最好创建一个抽象类:-)

【讨论】:

  • 只是一个缺少一些方法的普通类。
  • @Tichodroma,正如 Hans 所说,您可以创建一个带有一些缺失方法的常规类(或者更好的是,一些引发 NotImplementedError 的方法)。不过也有ABC(抽象基类),也可以用元类构建自己的抽象类系统。
  • 请参阅docs.python.org/library/abc.html 了解抽象基类。但是,抽象基类对于您想要做的事情来说确实是多余的。在此处查看抽象基类的基本原理:python.org/dev/peps/pep-3119
  • 当您想知道如果更改某些数据类型实现会发生什么(在内存和时间效率方面)时,我认为猴子补丁只是完美的答案。您可以在“隐藏”模块中编写新实现,然后将其“插入”以比较时间和内存使用情况。
  • monkeypatching 有效,但它不是动态的或可预测的,而且绝对不是自动的......我想知道你是否可以建立一个工厂来为给定模块创建代理,然后将其粘贴到 sys.modules而不是模块对象本身,因此您可以在导入时动态自动将函数拉入导入命名空间中引用的模块代理实例...
【解决方案2】:

如果你在一个模块中这样做,如果有一天在同一个程序中,一个模块想要将你的通用模块与一个实现一起使用,而另一个模块想要将它与另一个模块一起使用,你就会遇到问题。

解决方案是编写一个模块,该模块主要包含一个提供所需服务的类。

以“随机”模块为例。所有模块函数,如“randint”、“uniform”、“gauss”,实际上都绑定到 random.Random 类的隐藏实例的方法。但是您也可以使用自己的 Random 类实例,或者通过重新定义一些关键方法来对其进行子类化,以更改生成随机数的方式,但保留所有有用的方法。

http://docs.python.org/library/random.html

【讨论】:

    猜你喜欢
    • 2013-01-09
    • 1970-01-01
    • 1970-01-01
    • 2013-03-19
    • 1970-01-01
    • 2017-06-21
    • 2023-04-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多