【问题标题】:Add validation to __call__ methods in Python在 Python 中为 __call__ 方法添加验证
【发布时间】:2016-04-14 01:04:10
【问题描述】:

我有大量源自 Function 类的类层次结构(例如,SineFunction 将是一个孩子),并且它们都实现了 __call__ 方法以及其他方法(例如派生或更多专门的数值方法)。

根据输入类型向这些__call__ 方法中的每一个添加通用逻辑的最简洁方法是什么?形式上,我想要类似的东西

def __call__(self,x):
    if isinstance(x,Distribution):
        return FunctionDistribution(x,self)
    else:
        # Go back to previous logic

对于Function 的每个子类。我可以在__call__ 的每个实现中添加super(),但这会很痛苦。有什么更容易实现的吗?

【问题讨论】:

  • FunctionDistribution 每个版本都一样吗?还是会因不同的__call__ 方法而有所不同?总是有一个论点吗?
  • 不确定它是否适用于您的情况,但您可能想查看single dispatch generic functions (introduced in 3.4),您可以在其中定义具有通用实现的全局函数,以及特定类型的特化。它可能会或可能不会与您当前基于“函子”的设计很好地吻合,但我认为它正在检查工作。

标签: python python-3.x inheritance design-patterns composition


【解决方案1】:

这样的事情怎么样?

class BaseFunction(object):
    def __call__(self, x):
        if isinstance(x, BaseFunction):
            return self._call(x)
        else:
            print("Fallback logic goes here")

    def _call(self):
        raise NotImplementedError

class ChildFunction(BaseFunction):
    def _call(self, x):
        print("Child function executed on x")

子类各自定义_call,回退逻辑驻留在父类中。

一个例子:

>>> a = BaseFunction()
>>> b = ChildFunction()
>>> c = 3
>>> b(a)
Child function executed on x
>>> b(c)
Fallback logic goes here

编辑:

顺便说一句,我对您的特定用例了解不多,但我的理解是isinstance 通常不是理想的选择,最好做某种duck typing。在这种情况下,您可能希望将 if(isinstance(... 语句替换为 try/except 块,您只需使用接口 好像 x 实现 BaseFunction 接口.

【讨论】:

  • 是的,它可以这样做,但是这意味着将每个实现的 __call__ 重命名为 _call,这很烦人。
  • @Literal 我想你实际上是在物理上重命名__call__,如果你已经有一个使用__call__的实现,但实际上你正在做的是实现一个额外的方法_call,并且原来的__call__ 继承自BaseFunction,如果不清楚的话。
  • 另外,这似乎是一个非常简单的搜索和替换。现在可能比设计一些只在运行时执行等效操作的奇怪元类更好。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-07-22
  • 2018-10-13
  • 2019-02-07
  • 1970-01-01
相关资源
最近更新 更多