The problem with "as" [was "Re: PEP 318"]
Skip Montanaro
skip at pobox.com
Tue Mar 23 11:07:00 EST 2004
>> With no extension beyond the current PEP 318 proposal, you might
>> postulate returns() and accepts() decorators:
>>
>> def foo(x, y) [accepts(int, float), returns(int)]:
>> ...
>>
>> which extend foo() with code to enforce input and output types.
>> Further, function attributes could be added which could be used by
>> tools like pychecker for intermodule type checking.
Joe> Not a big fan of that syntax - I have to keep the parameter names
Joe> and types in sync by counting.
Here's a dummy example from the in-progress version of the PEP:
def accepts(*types):
def check_accepts(f):
def new_f(*args, **kwds):
for (a, t) in zip(args, types):
assert isinstance(a, t), \
"arg %r does not match %s" % (a,t)
return f(*args, **kwds)
assert len(types) == f.func_code.co_argcount
return new_f
return check_accepts
def returns(type):
def check_returns(f):
def new_f(*args, **kwds):
result = f(*args, **kwds)
assert isinstance(result, type), \
"return value %r does not match %s" % (result,type)
return result
return new_f
return check_returns
def func1(arg1, arg2):
return arg1 * arg2
func1 = accepts(int, (int,float))(func1)
func1 = returns((int,float))(func1)
print func1(5, 3.0)
print func1(5, 3)
def func2(arg1, arg2):
return str(arg1 * arg2)
func2 = accepts(int, (int,float))(func2)
func2 = returns((int,float))(func2)
try:
print func2(5, 3.0)
except AssertionError, msg:
print msg
def func3(arg1, arg2, *rest, **kwds):
r = arg1 + arg2
print "r:", r
print "rest:", rest
print "kwds:", kwds
if 'result' in kwds:
return kwds['result']
return r
func3 = accepts(int, int)(func3)
func3 = returns(int)(func3)
print func3(3,5,'a','b','c',other="47")
print func3(3,5,'a','b','c',result=47)
Note that check_accepts() does the counting for you. If you wanted type
declarations in the language I agree it would be more natural for the
arguments and their types to be side-by-side, but then it wouldn't be
Python. ;-)
Joe> For decorators in general, I like
Joe> def foo() as [decor1, decor2, decor3]:
Joe> You get an explicit list syntax, but it's set off by a keyword so
Joe> they don't run together to the eye. Because the keyword keeps it
Joe> unambiguous, you could even allow a tuple instead of a list: "def
Joe> foo() as (x, y, z)".
I don't understand how
def foo() as [decor1, decor2, decor3]:
is somehow less ambiguous than
def foo() [decor1, decor2, decor3]:
The language parser certainly wouldn't care.
Joe> So I definitely favour a keyword, but perhaps "as" is to generic.
Joe> What about "has" or "with"?
I don't think any keyword adds enough to make it preferable over just a
bracketed sequence of decorators. Python supports:
import foo as f
The use of "as" makes perfect sense in that context.
I'd prefer prepositional keywords actually be consistent with their English
usage. It's just line noise and is likely to provide some stumbling block
of programmers whose command of the English language is not stellar. What
we really would say in English is
Define function foo taking no arguments as modified by decor1, decor2
and decor3.
No single preposition is going to read correctly as a replacement for "as
modified by", nor do we need all those other bits of English ("function",
"taking no arguments") to tell us that this is a Python function definition.
This isn't SQL or COBOL, and it's certainly not English. My vote is to
dispense with the pseudo-keyword idea altogether.
Skip
More information about the Python-list
mailing list