Is it possible to find out if an object is of a certain type or of a
type derived from this type?
>>> issubclass(Example, object)
>>> issubclass(AnotherExample, object)
>>> issubclass(AnotherExample, Example)
>>> issubclass(Example, AnotherExample)
>>> isinstance(Example, type)
This is true because type is the metaclass of object. Though you don't
have to understand it. ;)
As I understand Python practice (and this is pretty limited, so
corrections or other use cases are welcome), type checking is
useful for overloading functions by argument type, e.g.,
__getitem__, which accepts both integers and slice objects as
keys for sequence types. Although in the case of __getitem__, et
al, it seems like the key type could have been unified to slices
(except I suppose the return type also change, er... except for
strings--oh never mind).
Yeps, this is one of the couple occasions you might want to know
something about the object's type. The few other use case I had where
mostly about the same pattern - "low-level" and somewhat dirty code.
> Although in the case of __getitem__, et
> al, it seems like the key type could have been unified to slices
> (except I suppose the return type also change, er... except for
> strings--oh never mind).
BTW: are type annotations to be backported to 2.x?
This is a dead horse beaten into the ground, full way through to china.
If you want typechecking - use a statically checked language. After all,
if you like to constrain yourself to certain types - why not benefit
from a compiler then?
I for once prefer to be able to pass object that behaves like e.g. a
file - think StringIO - to something taking a file, instead of
introducing a interface-maze like the java.io-hierarchy to capture each
possible thinkable aspect of file IO in a separate interface - and then
hoping that the third party library was careful enough to only require
what is really needed.
> So I have to give up the concept that argument types are part of the
> interface or signature?
Nope - you have to give up the notion of type you learned from
statically typed languages, and get used to the one used in dynamically
typed languages. Same word, different concept, really.
> Honestly, I don't like that. Granted; not having
> strict type checking makes for great flexibility but the price is you
> either write typchecking code or let the error propagate into the
> function or method.
Just tell me: what will happens if, *in Python*, you "write typechecking
code" ? Surely, when you'll (possibly wrongly) conclude you don't
have the "correct" type (meaning: the one you expected when writing your
code), you'll raise an exception, won't you ? (I can't imagine what
else...). So ask yourself: in which way will the final result be
different from would very probably happens without the "typecheking
code" ? In *both* cases, you end up with a runtime exception.
Granted, without "typechecking", there can be a couple corner cases
where you end up with incorrect results instead of an exception (like
your user passed a string where you expected a sequence which is *not* a
string). These corner cases might be worth the most minimal possible
check. As far as I'm concerned, I've run into this kind of corner case
perhaps half a dozen time in 7+ years. And usually because I (as a user
of someone else's code) failed to read the doc - which is my
responsability, the author's.
 dynamic typing means that two totally unrelated types may both
implement the expected (implied) interface. You just can't hope to know
by advance the exhaustive list of classes that will implement the
interface your code expects.
> I hope type annotations in py3k will allow for
> something like constraints in C# where you can tell the caller right
> away she's doing something wrong.
Lord have mercy. As Diez mentions, if you want static type checking,
then don't use a dynamically typed language. But trying to fight against
the language is not going to buy you much.
> So ask yourself: in which way will the final result be different
> from would very probably happens without the "typecheking code" ? In
> *both* cases, you end up with a runtime exception.
The idea behind such type checks is to make sure type errors are
caught as early as possible. Exceptions caught later, the philosophy
goes, are harder to debug because by then the cause of the problem can
be obscured. Consider an object of the wrong type passed to a method:
the method can store the object in its own instance attribute, and
keep working on something else. Then, much later, the faulty object
gets actually used and the error is raised. By the time the exception
is thrown, you have no idea where the offending object came from.
Personally, I consider the loss in flexibility to outweigh any
benefits of overeager type checks. Besides, type checks are only one
of the many possible constraints you could check in your objects, yet
proponents of type checks tend to treat them as somehow much more
important or fundamental.
Hopefully Python 3's support for abstract base classes will provide a
standard way to have our cake and eat it by allowing declarative
subtypes. That way type checks will be possible to prevent accidents,
but without compromising flexibility. Pure "duck typing" will be made
a bit more verbose, but not impossibly so.
You're Stockholmed to the gills by the crappy and nearly useless type
systems that you've been exposed to. If you're going to expound on the
merits of statically checked type systems, you should first gain some
experience with the ML family of languages, that actually have real
type systems without casts (like Python!), no escape hatches, and
guarantee the static type correctness of all programs.
Once you've done that, you'll hate the limited, verbose and cumbersome
C# type system and you'll be in a better situation to appreciate both
static and dynamic typing.
On a more pragmatic basis, there are only 2 kinds of type errors in Python:
1: The object passed doesn't implement the correct interface, and will
raise an error when called. This will be caught by a unit test.
2: The object passed implements something that looks like the right
interface, but implements it incorrectly. This will be caught by a
Note that both these errors will be caught by behavior exercising unit
tests and do not rely on any sort of "typechecking code" to be
written. Explicit typechecking in Python is done only when you need to
dispatch on type, not because you feel like generating spurious
That's the theory, yes. In practice, when such a situation occurs, it's
usually easy to track down the problem: just add a temporary check in
the method (or around it - using a decorator), rerun the program and
you'll be done. Once the faulty code is corrected, remove the check.
>> function or method. I hope type annotations in py3k will allow for
>> something like constraints in C# where you can tell the caller right
>> away she's doing something wrong.
[language rant snipped]
> On a more pragmatic basis, there are only 2 kinds of type errors in Python:
> 1: The object passed doesn't implement the correct interface, and will
> raise an error when called. This will be caught by a unit test.
> 2: The object passed implements something that looks like the right
> interface, but implements it incorrectly. This will be caught by a
> unit tests.
So if I use your code I need to read all of it to understand how "file
like" something for bla(filelike) needs to be to be able to write
unittests? Or do your unittests magically detect all possible callers
and send them email with nice warnings?
> Note that both these errors will be caught by behavior exercising unit
> tests and do not rely on any sort of "typechecking code" to be
> written. Explicit typechecking in Python is done only when you need to
> dispatch on type, not because you feel like generating spurious
Do you prefer situations like Hrvoje has descibed two post below?
To reiterate: I'd like to have a TypeError: "foo called with <str>,
<Point> expected" which is concise and informative for the caller,
rather than have him hunt down obscure errors in totally unrelated code
like AttributeError: 'str' object has no attribute 'move'.
My unit tests assert that operations perform as desired. Yours should
to. If they don't, your code might not behave as desired. Those are
called "bugs". Real live type errors are a subclass of bugs. Type
errors that occur because you'd didn't sufficiently placate the
compiler are not bugs, they are obnoxious.
In my Python work, I have *never* had a bug occur in production that
would have been caught by a C++/Java/C# style type system.
Are you seriously suggesting here that there should be a type for
every possible combination of methods and attributes that might be
needed for a file like object?
> > Note that both these errors will be caught by behavior exercising unit
> > tests and do not rely on any sort of "typechecking code" to be
> > written. Explicit typechecking in Python is done only when you need to
> > dispatch on type, not because you feel like generating spurious
> > errors.
> Do you prefer situations like Hrvoje has descibed two post below?
> To reiterate: I'd like to have a TypeError: "foo called with <str>,
> <Point> expected" which is concise and informative for the caller,
> rather than have him hunt down obscure errors in totally unrelated code
> like AttributeError: 'str' object has no attribute 'move'.
The type error is *wrong*, and you only want it because you think
backwards. The error is not that what was passed was the wrong type,
because "type" is an ephemeral concept in Python. The problem was that
the thing passed doesn't have a "move" method or, possibly, that the
move method didn't do the right thing. There's no reason whatsoever
that I should need to inherit from your Point class just to make this
method work (there's actually a corner case where you do, which is
with types implemented in C, but I'll leave that alone for now).
I reiterate my suggestion to use Haskel, or another language with type
inference, because that's what you really want, if you're going to go
the static typing route.
If you're looking for static typing, you're in the wrong newsgroup.
And even if you are, manifest typing where you need to declare
everything by hand and then force the compiler to ignore the
declarations in order to compile anyway is a dead end. If you find
benefit in static typing and want to write your code that way, there
are better approaches, like ML-style type inference.