Python工厂注册的最佳方法是什么?

5
这是一个关于哪种方法被认为是最符合Python习惯的问题。我不是在寻找个人意见,而是想要了解惯用法。我的背景不是Python,这会对我有所帮助。
我正在开发一个Python 3项目,它是可扩展的。这个想法类似于工厂模式,但它是基于函数的。
基本上,用户将能够创建一个自定义函数(跨包和项目),我的工具可以找到并动态调用它。它还将能够使用柯里化传递参数(但该代码未包含在此处)。
我的目标是让这个项目遵循良好的Python习惯。我在两种策略之间犹豫不决。由于Python不是我的专业,我想知道以下做法的优缺点:
  1. Use a decorator

    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]
    

    Then, the following function is automatically registered...

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

    This seems reasonable, but does appear slightly magical to those who are not familiar with decorators.

  2. Force sub-classing of an abstract class and use __subclasses__()

    If subclasses are used, there's no need for registration. However, I feel like this forces classes to be defined when a full class may be unnecessary. Also, the use of .__subclasses__() under the hood could seem magical to consumers as well. However, even Java can be used to search for classes with annotations.

  3. Explicit registration

    Forget all of the above and force explicit registration. No decorators. No subclasses. Just something like this:

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

Python基金会推广的唯一标准实践是PEP 8。而PEP 8仅仅是一个指导方针,适用于“主要Python发行版中标准库所包含的代码”。它强调了这只是一个指导方针,而不是严格的建议。但更重要的是,它与高级“设计模式”等问题几乎没有关系,也与您的具体问题无关。 - abarnert
我明白了,@abarnert。谢谢你。这很有道理。虽然我希望PEP 8之外还有其他建议,但我想灵活性也允许社区淘汰和发展首选实践。这种艰难的决定通常会让人们根深蒂固,我希望避免无谓的争论。 - Ben Reed
如果您想要一些主观评论:核心开发人员编写的代码,甚至是标准库,都可以执行这两个操作(以及其他选项,例如需要特定的基类或元类)。例如,isinstance(iter([1]), collections.abc.Iterable) 为真的原因是 collections.abc 调用了 Iterator.register(bytes_iterator)(并且术语表甚至解释了这种“虚拟子类化”,因此它不仅仅是一些隐藏在封面下的实现细节)。 - abarnert
2
但是,如果你不想使用装饰器的主要原因是它们“对于不熟悉装饰器的人来说似乎有点神奇”,我认为这不是一个很好的理由,除非你的代码主要是给初学者或只偶尔使用 Python 的人阅读。装饰器是语言的重要特性,任何使用它们的项目的开发人员都会很快掌握它们。 - abarnert
@abarnert说得有道理。有趣的是两者都在stdlib中使用。我认为装饰器模式在这里很吸引人。只是想确保我没有违反一些不良实践。 - Ben Reed
显示剩余2条评论
1个回答

2
这个问题没有答案。
Python基金会唯一推广的标准实践是PEP 8。
PEP 8与像这样的高级“设计模式”问题几乎没有关系,尤其是与您的具体问题无关。
即使有关联,PEP 8明确规定只是“在主要Python发行版中组成标准库的代码”的指南,Guido已经拒绝了使其成为应强制执行于每个Python项目的广泛标准的建议。
此外,它强调了它只是一个指南,而不是严格的建议
当然,有主观原因喜欢某个设计而不是另一个。
理想情况下,这些主观原因通常会受到社区一致认为什么是“惯用的”或“Python式”的驱动。但是,这种社区共识并没有以某种客观的来源书面记录下来,你无法引用它。
可能会有一些Python之禅的论点,但它本身只是Tim Peters试图将Guido自己的主观指导方针浓缩成简洁的语句集合,而不是客观来源。(任何人只需简要查看例如python-ideas列表,就能看到几乎任何问题的两个方面都可以引用Python之禅...)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接