这是一个关于哪种方法被认为是最符合Python习惯的问题。我不是在寻找个人意见,而是想要了解惯用法。我的背景不是Python,这会对我有所帮助。
我正在开发一个Python 3项目,它是可扩展的。这个想法类似于工厂模式,但它是基于函数的。
基本上,用户将能够创建一个自定义函数(跨包和项目),我的工具可以找到并动态调用它。它还将能够使用柯里化传递参数(但该代码未包含在此处)。
我的目标是让这个项目遵循良好的Python习惯。我在两种策略之间犹豫不决。由于Python不是我的专业,我想知道以下做法的优缺点:
我正在开发一个Python 3项目,它是可扩展的。这个想法类似于工厂模式,但它是基于函数的。
基本上,用户将能够创建一个自定义函数(跨包和项目),我的工具可以找到并动态调用它。它还将能够使用柯里化传递参数(但该代码未包含在此处)。
我的目标是让这个项目遵循良好的Python习惯。我在两种策略之间犹豫不决。由于Python不是我的专业,我想知道以下做法的优缺点:
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.
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.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)
isinstance(iter([1]), collections.abc.Iterable)
为真的原因是collections.abc
调用了Iterator.register(bytes_iterator)
(并且术语表甚至解释了这种“虚拟子类化”,因此它不仅仅是一些隐藏在封面下的实现细节)。 - abarnert