Re: Decorator for Enforcing Argument Types
- From: "George Sakkis" <george.sakkis@xxxxxxxxx>
- Date: 22 Dec 2006 14:05:48 -0800
John Machin wrote:
Peter Wang wrote:
Bruno Desthuilliers wrote:
<my humble opinion>
Python is dynamic, and fighting against the language is IMHO a really
bad idea. The only places where theres a real need for this kind of
stuff are when dealing with the "outside world" (IOW : inputs and
outputs). And then packages like formencode can do much more than mere
type-checking
</my humble opinion>
I don't think proper use of type checking is "fighting against the
language". The goal of any language is to enable programmers to
express their intent in a form that executes correctly.
Python is extremely expressive but there is a trade-off with
correctness - you can easily say something that you don't mean. Unit
testing is sometimes sufficient, but it can never span the infinite
space of potential errors. Type-checking method signatures guarantees
a certain amount of low-level correctness, and most type-checking
mechanisms also serve as documentation aids.
I think that with a sufficiently sophisticated type checking syntax,
one can get the best of both worlds. If the type checker understood
interfaces (like PyProtocols) and its syntax had the flexibility to
indicate sets of allowed arguments and aggregates of allowed
types/interfaces, it would cover the majority of cases without limiting
expressive power.
I understand that we're all adults, but it's still nice to have the
computer tell us when we're being childish. :)
Your comments on the following cut-down and disguised version of a
*real-world* example would be appreciated:
@accepts(object, (int, float))
def tally(self, anobj):
self.total += anobj
I assure you that the comments of a caller whose code did this:
fubar.tally(someobj)
and got this:
AssertionError: arg 12345678901L does not match (<type 'int'>,
<type 'float'>)
are definitely *not* repeatable in front of the children.
I guess this is not the 'accepts' decorator of the typecheck module;
with that you'd rather write it as @accepts(Self(), Number) and prevent
this error (http://oakwinter.com/code/typecheck/tutorial/methods.html).
I have also a very recent real-world example to share, from the other
side of the fence this time. It's even worse because it's an error that
passes silently. Cut-down version follows:
@cherrypy.expose
def retrieve(self, **kwds):
queries = kwds['q']
rows = self._selectRows(*queries)
# more stuff
'q' here is a multiselect field that is binded to a list of selected
strings. Or so I thought, until someone noticed bizarre results in some
cases. Turns out that if you select a single item from the select box,
'q' is binded to a string instead of a list of length 1, so instead of
retrieving 'apple', she got back the results for 'a', 'p', 'p',
'l','e'.
Bottom line, type checking is a tricky business. In some sense it's
similar to the recall/precision tradeoff in information retrieval. With
stricter type checking, you can increase the precision but may hurt the
recall, i.e. valid code is rejected, as in your example. And vice
versa, loosing up the type checks increases the recall but may hurt the
precision, as in my example.
George
.
- Follow-Ups:
- Re: Decorator for Enforcing Argument Types
- From: Bruno Desthuilliers
- Re: Decorator for Enforcing Argument Types
- References:
- Decorator for Enforcing Argument Types
- From: Chris
- Re: Decorator for Enforcing Argument Types
- From: Bruno Desthuilliers
- Re: Decorator for Enforcing Argument Types
- From: Peter Wang
- Re: Decorator for Enforcing Argument Types
- From: John Machin
- Decorator for Enforcing Argument Types
- Prev by Date: Re: One module per class, bad idea?
- Next by Date: attribute decorators
- Previous by thread: Re: Decorator for Enforcing Argument Types
- Next by thread: Re: Decorator for Enforcing Argument Types
- Index(es):
Relevant Pages
|
Loading