Python类型检查与继承问题
我有一段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
了。