On Nov 14, 1:27 pm, [EMAIL PROTECTED] wrote: > On Nov 14, 12:47 am, George Sakkis <[EMAIL PROTECTED]> wrote: > > > > > > > On Nov 13, 10:55 pm, Steven D'Aprano <[EMAIL PROTECTED] > > > cybersource.com.au> 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): > ...run 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 -- http://mail.python.org/mailman/listinfo/python-list