@decorators
Mark Bottjer
mark_bottjer at hotmail.com
Wed Aug 11 13:33:11 EDT 2004
Mark 'Kamikaze' Hughes wrote:
> You can already do pre- and post-conditions without new syntax:
>
> import types
> def intdiv(a, b):
> # preconditions
> assert type(a) == types.IntType
> assert type(b) == types.IntType
> assert b != 0
> rc = None
> try:
> # body
> rc = a // b; return rc
> finally:
> # postconditions
> assert type(rc) == types.IntType
>
> If assignment was an expression, that return would be a little nicer,
> but it's acceptable.
Sorry, but to me this is ugly. The preconditions aren't so bad (in fact,
much of my code has just such lines in it), but that postcondition block
is awful. It looks arbitrary, hides the real "meat" of the function, and
requires the construction of an exception frame when one shouldn't
really be needed. It works, certainly, but I think we'll have to "agree
to disagree" about how acceptable this syntax is. :)
> Mark Bottjer <mark_bottjer at hotmail.com>
> wrote on Fri, 06 Aug 2004 16:10:37 -0400:
>
>> Exactly. What's more, I don't think that decorators are really the
>> ideal way to express DBC, either. For one thing, pre and post
>> conditions often want access to at least the argument list, and often
>> to the internal variables of the definition. I don't think that this
>> will be possible with the decorators as proposed, since they are
>> outside the scope of the function.
After more thought, I think that it might be possible using decorators
and subfunctions. Shouldn't the following be workable?
import types
@pre_and_post
def intdiv(a, b):
def __pre():
assert type(a) == types.IntType
assert type(b) == types.IntType
assert b != 0
def __post():
assert type(rc) == types.IntType
return a // b
Where pre_and_post effectively wraps intdiv with the statement sequence:
intdiv.__pre()
try:
return intdiv( *args)
finally:
intdiv.__post()
This is functionally equivalent to your example (it even still requires
the try/finally). But I suggest that this version is more understandable
because it breaks the code up by what it does: __pre collects all the
preconditions, __post collects all the postconditions, and the body is
left alone. Theoretically, we could even globally enable or disable DBC
by having pre_and_post switch on some global variable, which would not
be possible with the conditions coded inline.
I'm not savvy enough with Python internals to code this up myself, but
I'm sure someone out there either can, or can tell me why it won't work.
-- Mark
More information about the Python-list
mailing list