Forgetting "()" when calling methods

Alex Martelli aleax at aleax.it
Sat Apr 26 06:05:42 EDT 2003


Terry Reedy wrote:

> 
> "Frantisek Fuka" <fuka at fuxoft.cz> wrote in message
> news:b8cadp$1fj9$1 at ns.felk.cvut.cz...
>> When I try to call methods, I sometimes forget to include the
>> parentheses. Instead of:
> 
> In Python, '()' is, in the proper context, the 'call me with the
> contained (possible none) arguments' operator.  So the above is much
> like saying, "When I try to calculate products, I sometimes forget to
> include the asterisk' -- like mathemeticians are in the habit of
> doing -- and then asking that interpreter start guession that missing
> binary operators are implied multiplication.

Hmmm -- not really: what the OP's asking is, rather, "much like" asking
that, when he does forget an asterisk, Python should give him an error
message rather than silently accepting his errant code and doing nothing
much with it.

And indeed, if you do forget an asterisk when coding a multiplication,
you do normally get an error except in very unlucky combinations of
circumstances -- e.g. if you ALSO omit the whitespace, are trying to
multiply variables named 'foo' and 'bar', and there is ALSO a variable
named 'foobar' that's accessible from the current scope.  In practice,
therefore, omitted asterisks aren't much of a problem for new Python
users -- they get error messages and soon learn to use the asterisk,

Omitted parentheses (to call an argument-less function or method) are 
more of a problem because the "error" is subtler -- some action that
should be performed just isn't, and the effects of the bug show up,
typically, much later.

Errors should not pass silently, unless explicitly silenced.  Yet,
that is exactly what this specific error -- omitting the trailing
parentheses when calling an argument-less function or method -- appears
to do to the Python beginner (who's coming from languages where the
parentheses aren't needed in this case, typically Pascal or something
derived from Pascal -- popular languages for teaching beginners, at
least around here).

I don't know what to DO about it, but some minor tweaks might help.
For example, I cannot think of any code I've ever written that would
break if methods (and functions) spouted a __nonzero__ special method
(or, of course, the C-coded equivalent thereof) raising an exception
with a clear error message -- this would at least provide prompt
error messages for usages such as "if x.amethod:" and the like.  And
MAYBE PyChecker could be enhanced to optionally warn about code that
gets an attribute from an object and does absolutely nothing with the
attribute it's gotten -- yes, this WOULD give warnings for the
reasonably common idiom of
    try: x.something
    except AttributeError: ...
but this isn't an idiom a beginner's all that likely to use, therefore
the *optional* nature of the warning might help -- beginners would get
the warning, advanced users would suppress it.

I think this may be important enough to warrant a PEP, as I have
already suggested to the OP.  Of course, like most all developments
in open-source software, it requires somebody interested enough in
the issue to push it forwards -- if it scratches nobody's itch, it's
best dropped.  But, the problem is not with the _code_ necessary to
enhance Python's error-diagnostics for these cases (can't speak about
PyChecker, which I've never hacked on, but the mod to the Python core
for what I've mentioned above IS quite simple) -- rather, the problem
is with defining exactly what issues we can solve, with what mods to
Python as it stands, giving the pro's and con's of each possible
solution (including that of doing nothing), and letting the BDFL
Pronounce about it all.  Exactly what a PEP is good for!


> the object resulting from the conditional expression.  The boolean
> value of function objects is always True.

Yes, and the latter is exactly the feature which I think we might
do away with -- I've never written any code USING it.

>> You can say to me "Don't forget to always include the parenteses"
> 
> Just as you should not forget the asterisk in multiplications.

But he'd reliably get prompt error messages for the latter error --
he doesn't for the former -- THAT is the problem.

>> I'm still curious if this cannot be somehow configured,
> 
> The consistency of Python expression evaluation is one of its basic
> features.  Fighting it is the path to frustration.

Yes, but there would be no inconsistency in decreeing that function
and method objects can't be transparently evaluated as true or false
in boolean contexts, any more than, say, in decreeing that complex
numbers cannot be compared for lesser/greater (a change that was in
fact done moving 1.5.2 -> 2.0) -- indeed the latter change, apparently
inspired by purism rather than pragmatism, did give me a little bit
of trouble (the keys.sort() step broke in a piece of code I had, that
was displaying a dictionary in an ordered way, when some keys were
complex) while the former (proposed) change wouldn't.


> Have you never yet typed in 'obj.meth.__doc__' at the interactive
> interpreter prompt?  That is possible precisely because 'obj.meth' is
> precisely what it claims to be.  Also, it should not be too long
> before you want to start abbreviating obj.meth and do something like
> 
> stack = []
> push = stack.append
> pop  = stack.pop
> #code using these three names, simple example being
> push(1); print stack
> # [1]
> print pop(), stack
> # 1, []

None of the changes I'm considering would in the least affect either
of these important use cases, nor the many other common ones (such
as putting functions and methods as values in lists or dicts, etc).


Alex





More information about the Python-list mailing list