Python type checking and inheritance
I have Python code that depends on type checking. I will try to formulate my problem in the language of mathematics so that she understands. I have several classes that correspond to subsets of each other and form an inheritance chain.
class Real(object):
pass
class Integer(Real):
pass
class Natural(Integer):
pass
And I have tuples containing types. Each of them corresponds to the domain of some function.
t1 = ( Real, Real )
t2 = ( Real , Integer )
I would like to do some form of type checking, which is given by another tuple ( Natural , Natural )
, if every coordinate in the tuple is a subclass of the specified domains. For example, for some function, getcompatibles
I would like to have:
getcompatibles( ( Real, Real ) ) = [ t1 ]
getcompatibles( ( Real, Integer ) ) = [ t1, t2 ]
getcompatibles( ( Natural, Natural ) ) = [ t1, t2 ]
getcompatibles( ( Natural, Real ) ) = [ t1 ]
The only solution I could come across was to run each of them for domain (t1, t2) through each of the types in __subclasses__
and check if it is isinstance
True for the given input.
This is extremely inefficient, is there perhaps a more pythonic way to do this?
a source to share
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)]
The name is_compatible
for something that is n't , the predicate is really, really confusing: why not give it a sensible name, for example getcompatibles
, so that a strong sounding predicate iscompatible
can be used instead of what I should have called compatible_pred
?
a source to share
Don't check types when you don't need to, and count on exception handling - with try
/ except
to catch cases where the expected violation is violated.
In Python, which is a "lazy typed" (but heavily typed, less frustrated purist) language, the call isinstance
will cost you multiple times overhead. The question I ask myself when faced with design questions like this is "If you don't want this function to handle Naturals pairs, why would you name it with them?" Presumably you are doing some kind of conditional branch based on is_compatible, I suggest you change it to conditional call.
Seeing how you are going to use the result of is_compatible will give you a more focused answer.
a source to share