哪种方式最适合 Python 工厂注册?

Posted

技术标签:

【中文标题】哪种方式最适合 Python 工厂注册?【英文标题】:Which way is ideal for Python factory registration? 【发布时间】:2018-12-06 22:46:47 【问题描述】:

这是一个问题,关于这些方法中的哪一种会被认为是最Pythonic。我不是在寻找个人意见,而是在寻找惯用语。我的背景不是 Python,所以这将对我有所帮助。

我正在开发一个可扩展的 Python 3 项目。这个想法类似于工厂模式,只是它是基于函数的。

基本上,用户将能够创建一个自定义函数(跨包和项目),我的工具可以定位并动态调用该函数。它还可以使用柯里化来传递参数(但此处不包含该代码)

我的目标是遵循良好的 Pythonic 实践。我在两种策略之间左右为难。而且,由于 Python 不是我的专长,我想知道以下做法的优缺点:

    使用装饰器

    registered = 
    
    def factoried(name):
        def __inner_factory_function(fn):
            registered[name] = fn
            return fn
        return __inner_factory_function
    
    
    def get_function(name):
        return registered[name]
    

    那么,下面的函数就自动注册了……

    @factoried('foo')
    def build_foo():
      print('hi')
    

    这似乎是合理的,但对于那些不熟悉装饰器的人来说确实有点神奇。

    强制对抽象类进行子类化并使用__subclasses__()

    如果使用子类,则无需注册。但是,我觉得这会在可能不需要完整类时强制定义类。此外,在引擎盖下使用.__subclasses__() 对消费者来说似乎也很神奇。然而,即使是 Java 也可以用来搜索带有注解的类。

    显式注册

    忘记以上所有内容并强制显式注册。没有装饰师。没有子类。就像这样:

    def build_foo():
      # ...
    
    factory.register('foo', build_foo)
    

【问题讨论】:

Python 基金会提倡的唯一标准实践是 PEP 8。而 PEP 8 只是“在主要 Python 发行版中包含标准库的代码”的指南。它强调了这只是一个指导方针,而不是严格的建议。但是,更重要的是,它与此类更高级别的“设计模式”问题几乎没有关系,与您的具体问题无关。 所以,唯一的答案是,就 PSF 的“推广标准做法”而言,你做什么都没有关系。唯一的决定方法是基于主观意见——这可能会受到更大的 Python 社区认为惯用的东西的指导,但这不会被写入任何你可以引用的客观文档中。 我明白了,@abarnert。谢谢你。这就说得通了。我的一部分希望有 PEP 8 之外的建议,但我想这种灵活性也允许社区淘汰和开发首选实践。 -- 像这样的艰难决定,人们似乎普遍认为是扎根的,我希望避免自行车脱落。 如果你想要一些主观的 cmets:核心开发人员编写的代码,甚至是标准库,都可以做到这两个(以及其他选项,比如需要特定的基类或元类)。例如,isinstance(iter([1]), collections.abc.Iterable) 为真的原因是collections.abc 调用了Iterator.register(bytes_iterator)(词汇表甚至解释了这种“虚拟子类化”,因此它不仅仅是隐藏在幕后的一些实现细节)。 但是如果你不使用装饰器的主要原因是它们“对那些不熟悉装饰器的人来说有点神奇”,我认为这不是一个很好的理由,除非你的代码是故意的主要由初级新手或只会谨慎使用 Python 的人阅读。装饰器是该语言的一个重要特性,任何从事使用它们的项目的人都会很快掌握它们。 【参考方案1】:

这个问题没有答案。

Python 基金会提倡的唯一标准做法是PEP 8。

PEP 8 与此类更高级别的“设计模式”问题几乎没有任何关系,尤其是与您的特定问题无关。

而且,即使这样做了,PEP 8 也明确地只是 "code comprising the standard library in the main Python distribution" 的指导方针,Guido 拒绝了将其作为某种范围广泛的标准的建议,该标准应该在每个 Python 项目中强制执行。

另外,它强调了it's only a guideline, not a rigid recommendation 的观点。


当然,偏爱一种设计而不是另一种设计是有主观原因的。

理想情况下,这些主观原因通常是由社区对什么是“惯用”或“pythonic”达成的共识所驱动的。但是,社区共识并没有作为您可以引用的客观来源写在任何地方。

The Zen of Python 可能有一些争论,但这本身只是 Tim Peters 试图将 Guido 自己的主观指导方针提炼成一系列精辟的声音片段,而不是客观来源。 (任何人只要看一眼,例如python-ideas 列表,就会发现几乎任何问题的双方都可以吸引禅宗……)

【讨论】:

以上是关于哪种方式最适合 Python 工厂注册?的主要内容,如果未能解决你的问题,请参考以下文章

论特定场景适合的设计模式之1:简单工厂模式

spring bean注册之bean工厂方式

设计模式_简单工厂模式

简单工厂模式 - python

python设计模式-创建型工厂方法模式

设计模式系列 - 简单工厂模式