[Tutor] class.__repr__: 'str' object is not callable???

Magnus Lyckå magnus@thinkware.se
Fri May 2 05:35:01 2003


At 20:25 2003-05-01 -0500, pan@uchicago.edu wrote:
>Question: where is the .name() method after the class
>is instanciated ? Simply overridden by the .name attribute
>and can no longer be accessed ?

No. The string attribute is in the in instance object, and
the method is in the class object, but it's probably a good
idea not to use the same name for a method as for an attribute,
since you can't use the normal shortcut to call methods, i.e.
via the instance.*)

 >>> class X:
...     def __init__(self):
...             self.y = 'I am an attribute'
...     def y(self):
...             return 'I am a method'
...
 >>> x = X()
 >>> print x.y
I am an attribute
 >>> print X.y
<unbound method X.y>
 >>> print x.__class__.y
<unbound method X.y>
 >>> print x.y()
Traceback (most recent call last):
   File "<interactive input>", line 1, in ?
TypeError: 'str' object is not callable
 >>> print X.y(x)
I am a method
 >>> print x.__class__.y()
Traceback (most recent call last):
   File "<interactive input>", line 1, in ?
TypeError: unbound method y() must be called with X instance as first 
argument (got nothing instead)
 >>> print x.__class__.y(x)
I am a method

Remember that everything (almost) is a first class object in
python. It would not make sense if y referred to different
objects when you did x.y or x.y().

For instance, an attribute might be callable:

 >>> class X:
...     def __init__(self):
...             self.y = int
...
 >>> x = X()
 >>> print x.y(4.34)
4

Here we want to access an attribute, not a method, even
if we have () after the attribute name.

You can also do something like:

a = SomeClass(1,2,3,4)
a_meth = a.method
for i in aLongRange:
     a_meth(i)

Here we want to access a method, even if we don't use () after
the method name.

This will save a namespace lookup inside the loop. It's a fairly
common way to increase the speed for method calls to small methods
that are called in a loop. (For a trivial method that just does
"self._cnt += 1" I get a 15-20% speedup for big loops, so this is
probably not very useful, but the general abaility to be able to
get to any object in a uniform way, whether it's a string, a module
or a function, is very useful.

*) You can view "x.y()" as shorthand for x.__class__.y(x). After
all, methods reside in classes (usually) and you need to feed then
an appropriate instance object as the first parameter.


--
Magnus Lycka (It's really Lyck&aring;), magnus@thinkware.se
Thinkware AB, Sweden, www.thinkware.se
I code Python ~ The shortest path from thought to working program