在静态类型语言中,为了解决下面的问题,我将使用接口(或抽象类等)。但我想知道在python中是否有更“pythonic”的方法
因此,请考虑以下情况:
class MyClass(object):
# ...
def my_function(self, value_or_value_provider):
if is_value_provider(value_or_value_provider):
self._value_provider = value_or_value_provider
else:
self._value_provider = StandardValueProvider(value_or_valie_provider)
# `StandardValueProvider` just always returns the same value.
上面的“值提供者”是定制类,它有get_value()
方法。当然,这个想法是用户可以实现的
现在,问题是:实现is_value_provider()
的最佳方式是什么?即,区分“单一价值”和“价值提供者”的最佳方式是什么
我想到的第一个想法是使用继承:引入带有空实现的基类BaseValueProvider
,并在文档中告知自定义“值提供者”必须从中继承。然后在is_value_provider()
函数中检查isinstance(objectToCheck, BaseValueProvider)
。我不喜欢这个解决方案的一点是,在这种情况下(特别是在python的情况下),继承似乎是多余的,因为我们甚至不能强迫一个派生实现get_value()
方法的人。此外,对于想要实现定制“值提供者”的人来说,这个解决方案意味着需要对模块有依赖性,该模块公开了BaseValueProvider
另一种解决方案是使用“trait-attribute”。也就是说,不用检查基类,而是用hasattr()
函数检查特定属性的存在性。我们可以检查get_value()
方法本身是否存在。或者,如果我们担心方法的名称太常见,我们可以检查专用的trait属性,比如is_my_library_value_provider
。然后在文档中告诉我们,任何定制的“值提供者”不仅必须有get_value()
方法,而且还必须有is_my_library_value_provider
。第二种解决方案似乎更好,因为它不滥用继承,并且允许实现定制的“值提供者”,而不依赖于提供基类的其他库
有人能评论一下哪种解决方案更可取(或者如果有其他更好的解决方案),为什么
编辑:稍微更改示例以反映这样一个事实,即值提供者将在以后存储和使用(可能多次)
我强烈建议使用^{}
您的代码将具有很高的可读性,通过ducktyping您可以稍后使其与您所想到的其他类型一起工作
为了避免与其他具有
get_value()
函数的对象混淆,Python习惯用法假定编码者是负责人,不会试图破坏他实现代码的系统,因此一个hasattr(obj, "get_value")
就足够了。如果类具有.get_value()
,则可以假定它是值提供者而不是值(否则,值就是值本身)^{<在值上,返回self
是非常无用的)相关问题 更多 >
编程相关推荐