使用Abstract Base类作为函数的参数(Python)

时间:2015-06-22 19:44:24

标签: python

如果我有一个名为BaseData的抽象基类,其函数update在其子类中被覆盖了不同的功能,我可以使用如下函数,我希望函数在将任何Child Class作为参数,并为相应的Child Class调用update函数。

def date_func(BaseData, time):
        result = BaseData.update(time) 
        lastrow = len(result.index)
        return result['Time'].iloc[lastrow],result['Time'].iloc[lastrow-100]

2 个答案:

答案 0 :(得分:2)

当然可以。 Python不关心,因为它不进行任何类型检查。

实际上,您可以使用提供兼容接口的任何类型,而不管该实例是否来自BaseData

答案 1 :(得分:0)

包含ABC名称作为参数名称不会将其仅限于ABC的子类。它所做的就是创建该名称的参数。

任何类型的任何对象都可以作为参数传递给任何函数或方法。任何对象 - 在这种情况下 - 没有update()将导致AttributeError被引发,但如果参数有一个update()方法可以接受给定的一个参数,它不会引起问题。

如果您想确定第一个参数是BaseData的子类,请按照下列步骤操作:

  1. 将参数重命名为data。这将使参数的名称不是阴影(“在此上下文中替换”)实际的BaseData
  2. 在函数的开头写if isinstance(data, BaseData):,标记已存在的所有内容。
  3. (可选)编写引发错误的else子句。如果不这样做,那么当类型检查失败时,将只返回None
  4. 现在您已经知道如何做您所要求的事情,您应该知道这样做几乎没有值得做的事情。同样,任何满足所需“协议”的对象都可以工作,并且不一定必须是ABC的子类。

    这遵循python的原则“请求宽恕而非许可”(或EAFTP),这让我们假设传递参数的人给出了兼容类型之一。如果您担心某人提供错误类型的可能性,那么您可以将代码包装在try-catch块中,以处理在出错时引发的异常。这就是我们“请求宽恕”的方式。

    通常,如果您要进行类型检查,那是因为您已准备好处理不同的协议集,并且定义这些协议的ABC也(最好)定义__subclasshook__()以便它不会只是检查该类是否是“已注册”的子类,而是遵循规定的协议。