Don't understand this "method mapping"

Terry Reedy tjreedy at home.com
Sat Jul 21 17:35:29 CEST 2001


"Bas Michielsen" <BMichielsen at compuserve.com> wrote in message
news:3B598059.42027565 at compuserve.com... (Cc'ed) to Bas

I am rearranging this message.  First the class:

> def linear( x_in, a=0): # a=0 is a stub to get past an error
condition
>     print "linear called, a =", a
>     return x_in
>
> class Curve:
>     map = linear
>
>     def use_map( self, x):
>         print "Using self.map = ", self.map
>         self.y = self.map( x)
>
>     def set_map( self):
>         self.map = linear

> # Test code (I am running Python 1.5.2)
> ## # Output produced by the above
I am intermixing these to make things clearer
>
> c = Curve()
> print c.map
> ## <method Curve.linear of Curve instance at 80c7380>

> c.use_map( 1.0)
> ## Using self.map =  <method Curve.linear of Curve instance at
80c7380>
> ## linear called, a = 1.0

> print c.y
> ## <__main__.Curve instance at 80c7380>
You apparently said print c, not c.y, which should be 1.0

> c.set_map()
> c.use_map( 1.0)
> ## Using self.map =  <function linear at 80b6dd0>
> ## linear called, a = 0

> print c.y
> ## 1.0

Now the questions:

> ## I am a beginner with Python and I don't understand why in the
code below
> ## the attribute `map' first represents Curve.linear

Because you made it so, or look like so.  Def always generate a
function.  When you make a function an attribute of a *class*, it gets
wrapped as a method.  To do so, either define the function in the
class body or assign an externally defined function: does not matter.
When you 'print' a function (or method), the definition name (stored
with the function) is used, whether or not that definition name is
currently bound to the function.  Try

 def f(): pass
g = f; del f
print g

and g will print as f even though there is no longer an f in the
module namespace.

Of course, since <linear> only expects one arg, calling c.map(1.0)
would generate an exception when c is added as the first argument.

> ## which also points to the external function linear

The function was defined externally, but except for *also* having a
name in the global dictionary (which you could delete after the class
definition), it it no more external than your function set_map.
Class.map is a method that wraps function <linear>.  Class.set_map is
a method that wraps function <set_map>.

> ## and then, after calling set_map,
> ## is simply the external function linear for a Curve object.

set_map() assigns <linear> as a *function* attribute map of the
*instance* c, which, having the map name, will mask the class
attribute map.  That is why the difference in the second use_mapp
output.

> ## I had expected that calling Curve.linear would be signalled as an
> ## attribute error because there is no method linear in class Curve

Correct.  It would if you were to do so directly, by that name, but
you never did!

> ## or otherwise that the two ways to initialise the map attribute
would be
> ## equivalent???

As explained above, Curve.map and c.map are different things.  They
only look alike because you called both indirectly.  Try print
id(linear), id(Curve.map), id(c.map).

Terry J. Reedy






More information about the Python-list mailing list