Forgetting "()" when calling methods

Steven Taschuk staschuk at telusplanet.net
Sat Apr 26 13:15:27 EDT 2003


Quoth Klaus Meyer:
> I also have made this mistake sometimes.
> 
> On reason, i think, is the mix of function-call and values, example:
> 
> import time
> print time.time()
> print time.timezone
> 
> You have to remember the doc of the module carefully to make no mistake.

Hm.  Yes and no.  In many cases such a mistake will make the code
fail dramatically with an informative exception.  For example, if
you forget that time.timezone is not a function and try to call
it, Python tells you exactly what you did wrong:

    >>> import time
    >>> time.timezone()
    Traceback (most recent call last):
      File "<stdin>", line 1, in ?
    TypeError: 'int' object is not callable

So from here you should think: 'int' object is not callable -> I
tried to call an 'int' object -> the code called time.timezone ->
time.timezone is an 'int' object -> time.timezone is not a
function.  At that point you might go digging in the documentation
to find out exactly what it is, but if you just forgot for a
moment, this ought to remind you adequately.

Similarly, if you forget that time.time is a function, then:

    >>> time.time + 5*60*60
    Traceback (most recent call last):
      File "<stdin>", line 1, in ?
    TypeError: unsupported operand types for +: 'builtin_function_or_method' and 'int'

And again: 'unsupported operand type for +' -> I added two things
which can't be added -> one is a builtin_function_or_method and
the other is an int -> 5*60*60 is an int -> time.time must be a
function -> I have to write "time.time()".

There are cases, of course, in which the problem passes silently
and just makes your program behave strangely.  I don't think
there's any good technological solution here (see below); my
feeling is that one just needs good troubleshooting skills.
Systematic investigation of what your code is and is not doing,
maybe sprinkling print and/or assert statements throughout the
code to gather data, forming and testing hypotheses about what
might be wrong...

(Aside: A lot of questions of the form "why doesn't this work?"
get answered here by programmers who are experienced enough that
the problem is obvious, and who consequently might have trouble
explaining how the querent could have figured it out themselves.
It would be nice to be able to point people at a good on-line
debugging tutorial for beginners; anybody know of such a thing?)

> In this case time() must be a function, because it has to read the actual 
> timer value, but must timezone be a value?

This makes it possible to write
    time.timezone = 5*60*60 # set local timezone to EST
for example.  (Actually I've never tried this, so I'm not sure it
works.)  Otherwise we'd have to have two functions gettimezone()
and settimezone(), which is slightly less convenient.

> My question about style:
> Should a Module/Class etc. return values, if possible, or better use 
> function to return values?

Depends on the circumstances.  If it feels like just a value then
it should be a value; if it feels like the result of an action or
computation then it should be a function's return value.

(The point of properties imho is that they let you take things
which (for implementation reasons perhaps) are actually actions
and make them feel like values for the user.  Sometimes this is
quite a win.)

> If PyChecker could check such cases this would be very helpful.

In general it's very hard (impossible, for practical purposes) to
determine ahead of time what a given name will refer to when a
given line of code is executed -- or even what type of object it
might refer to.  I don't see how pychecker could determine that
time.timezone() is wrong; it could easily be right.

-- 
Steven Taschuk                            staschuk at telusplanet.net
Every public frenzy produces legislation purporting to address it.
                                                  (Kinsley's Law)





More information about the Python-list mailing list