G
George Sakkis
Explicit type checking is not typically seen in Python code, and usually
that's not a big problem; most typing errors are likely to raise a TypeError
or AttributeError sooner than later. There are cases, though, where typing
errors are not caught (at least not early) because different classes happen
to have methods with the same name; that's really subtle with the special
methods like __eq__, __hash__, etc. that are common to all (or at least
many) classes.
It happened to me when I was passing arguments of some type B to a function
instead of the correct type A; these arguments were entered as keys in a
dictionary, and since both A and B were hashable the interpreter didn't
complain. Of course, when later I was trying to retrieve the A()s I thought
I had entered, I couldn't find them (debugging was even harder in this case
because B was essentially a wrapper for A and the __str__ of both classes
was deliberately the same, so the A()s appeared to be in the dict; that's
not the issue here though).
I wonder if people have come up with such pitfalls in practice or I was just
careless. In any case, I was tempted enough to write a simple extensible
runtime type checking module, which can be handy, at least during
development. It's extensible in the sense that a "type" can be any
constraint, not just a python type or class. Here's an example of usage:
def foo(name, age, children, phonebook):
assert TypeChecker.verify(
(age, int),
(name, TupleOf((str,str))),
(children, ListOf(Child)),
(phonebook, DictOf(str, ContainerOf(Phone))))
foo(name = ("Paul", "Smith"),
age = 23,
children = [Child(), Child()],
phonebook = {
"Mike": (Phone(), Phone()),
"office": [Phone()]
})
ContainerOf, TupleOf, ListOf and DictOf are all extensions of the abstract
TypeChecker class, providing some limited but common templated-type
checking. Of course in practice most complex structures (e.g. phonebook)
would be encapsulated in a class, so it's questionable whether such
functionality adds up anything to a list of "assert isinstance(object,type)"
statements. Any ideas or suggestions are welcome.
George
that's not a big problem; most typing errors are likely to raise a TypeError
or AttributeError sooner than later. There are cases, though, where typing
errors are not caught (at least not early) because different classes happen
to have methods with the same name; that's really subtle with the special
methods like __eq__, __hash__, etc. that are common to all (or at least
many) classes.
It happened to me when I was passing arguments of some type B to a function
instead of the correct type A; these arguments were entered as keys in a
dictionary, and since both A and B were hashable the interpreter didn't
complain. Of course, when later I was trying to retrieve the A()s I thought
I had entered, I couldn't find them (debugging was even harder in this case
because B was essentially a wrapper for A and the __str__ of both classes
was deliberately the same, so the A()s appeared to be in the dict; that's
not the issue here though).
I wonder if people have come up with such pitfalls in practice or I was just
careless. In any case, I was tempted enough to write a simple extensible
runtime type checking module, which can be handy, at least during
development. It's extensible in the sense that a "type" can be any
constraint, not just a python type or class. Here's an example of usage:
def foo(name, age, children, phonebook):
assert TypeChecker.verify(
(age, int),
(name, TupleOf((str,str))),
(children, ListOf(Child)),
(phonebook, DictOf(str, ContainerOf(Phone))))
foo(name = ("Paul", "Smith"),
age = 23,
children = [Child(), Child()],
phonebook = {
"Mike": (Phone(), Phone()),
"office": [Phone()]
})
ContainerOf, TupleOf, ListOf and DictOf are all extensions of the abstract
TypeChecker class, providing some limited but common templated-type
checking. Of course in practice most complex structures (e.g. phonebook)
would be encapsulated in a class, so it's questionable whether such
functionality adds up anything to a list of "assert isinstance(object,type)"
statements. Any ideas or suggestions are welcome.
George