"In object-oriented programming, the Liskov substitution principle is a
PARTICULAR definition of subtype..." [emphasis added]
There are other definitions possible. Also be careful of confusing
subclasses with subtypes:
http://en.wikipedia.org/wiki/Subtype
http://en.wikipedia.org/wiki/Subclass_(computer_science)
Python doesn't have types in the sense of the Liskov substitution
principle, because Python's subclass relationship need not imply
substitutability. In fact, the requirement for substitutability is quite
restrictive. (Whether it is a good thing or a bad thing is open for
debate.)
With duck typing and/or delegation, one might create a new class which is
substitutable for the original class, without it being a subclass. And
contrariwise, one might create a subclass which isn't substitutable for
the original class. Inheritance is a *mechanism* for getting identical or
similar behaviour without the anti-pattern of copy-and-paste programming
(code duplication). There's no logical requirement that two objects with
identical behaviour in one aspect must necessarily be substitutable for
each other:
chicken.lay_egg()
shark.lay_egg() # some sharks lay eggs
I don't see this as a bad thing (unless of course they are *supposed* to
be substitutable, in which case the failure to be so is a bug).