Paul McGuire ptmcg at
Fri Nov 14 22:07:09 CET 2008

On Nov 14, 1:27 pm, prueba... at wrote:
> On Nov 14, 12:47 am, George Sakkis <george.sak... at> wrote:
> > On Nov 13, 10:55 pm, Steven D'Aprano <st... at REMOVE-THIS-
> >> wrote:
> > > Take this example:
> > > def foo(alist):
> > >     alist.sort()
> > >     alist.append(5)
> > > The argument can be any object with sort and append methods (assumed to
> > > act in place). But what happens if you pass it an object with a sort
> > > method but no append? The exception doesn't occur until *after* the
> > > object is sorted, which leaves it in an inconsistent state. This can be
> > > undesirable: you might need the function foo to be atomic, either the
> > > entire function succeeds, or none of it.
> > In this example atomicity is not guaranteed even if alist is a builtin
> > list (if it contains a complex number or other unorderable object),
> > let alone if not isistance(alist, list). It gets worse: false
> > positives are less likely for full-spelled methods with well-known
> > names such as "sort" and "append"  (i.e. if hasattr(alist, 'append'),
> > alist.append *probably* does what you think it does), but good luck
> > with that when testing for __getitem__, __iter__ for more than one
> > pass, __call__, and other special methods with ambiguous or undefined
> > semantics.
> > Let's face it, duck typing is great for small to medium complexity
> > projects but it doesn't scale without additional support in the form
> > of ABCs/interfaces, explicit type checking (at compile and/or run
> > time), design by contract, etc. It must not be a coincidence that both
> > Zope and Twisted had to come up with interfaces to manage their
> > massive (for Python at least) complexity.
> > George
> What would be actually interesting would be an switch to the python
> interpreter that internally annotated function parameters with how
> they are used in the function and raised an exception as soon as the
> function is called instead of later. Failing earlier rather than
> later. Example:
> def sub(x,y):
> some stuff
> ...print x[2]
> ...return y.strip().replace('a','b')
> internally python generates:
> def sub(x: must have getitem, y: must have strip and replace)
> sub([1,2,3,4],5)
> Error calling sub(x,y): y has to have strip() method.- Hide quoted text -
> - Show quoted text -

No, this would mean:
def sub(x: must have getitem, y: must have strip, and y.strip must
return something that has replace)

Or to be even more thorough:
def sub(x: must have getitem, y: must have strip and strip must be
callable, and y.strip must return something that has replace and
replace must be callable)

So even this simple example gets nasty in a hurry, let alone the OP's
case where he stuffs y into a list in order to access it much later,
in a completely different chunk of code, only to find out that y
doesn't support the complete string interface as he expected.

-- Paul

More information about the Python-list mailing list