Python类型检查与继承问题

2 投票
2 回答
1289 浏览
提问于 2025-04-15 22:54

我有一段Python代码,它需要检查数据类型。我会用数学的语言来描述我的问题,这样会更清楚。我有几个类,它们之间有包含关系,形成了一条继承链。

class Real(object):
    pass

class Integer(Real):
    pass

class Natural(Integer):
    pass

我还有一些元组,这些元组包含了类型。每个元组对应着某个函数的定义域。

t1 = ( Real, Real )
t2 = ( Real , Integer )

我想做一种类型检查,比如给定一个元组 ( Natural , Natural ),检查这个元组中的每个元素是否都是指定定义域的子类。例如,对于某个函数 getcompatibles,我希望能够这样做:

getcompatibles( ( Real, Real ) ) = [ t1 ]
getcompatibles( ( Real, Integer ) ) = [ t1, t2 ]
getcompatibles( ( Natural, Natural ) ) = [ t1, t2 ]
getcompatibles( ( Natural, Real ) ) = [ t1 ]

我想到的唯一解决办法是遍历每个定义域(t1, t2),然后检查每个类型的 __subclasses__,看看给定的输入是否满足 isinstance 的条件。

不过,这样做效率非常低,不知道有没有更Pythonic的做法呢?

2 个回答

2

在你不需要检查类型的时候,就别去检查,依靠异常处理来应对那些不符合预期的情况,使用 try / except 来捕捉这些错误。

在Python中,这是一种“懒惰类型”的语言(但它是强类型的,免得让我惹怒那些纯粹主义者),如果你反复调用 isinstance,那肯定会增加额外的开销。当我面对这样的设计问题时,我会问自己:“如果你不想让这个函数处理自然数的对,那你为什么还要用它来处理呢?”大概你是基于 is_compatible 来做某种条件判断,我建议你把这个改成条件调用。

如果能看到你打算如何使用 is_compatible 的结果,可能会给出更有针对性的答案。

4
def compatible_pred(obj_types, fun_signature):
  if len(obj_types) != len(fun_signature): return False
  return all(issubclass(of, ft) for of, ft in zip(obj_types, fun_signature))

def is_compatible(obj_types, fun_signatures=(t1, t2)):
  return [t for t in fun_signatures if compatible_pred(obj_types, t)]

这个 is_compatible 的名字让人很困惑,因为它其实并不是一个判断条件的东西。为什么不给它起个更合适的名字,比如 getcompatibles 呢?这样的话,听起来像是判断条件的 iscompatible 就可以用来表示我现在叫的 compatible_pred 了。

撰写回答