problems with the types module

Terry Reedy tjreedy at udel.edu
Wed Dec 11 15:51:45 EST 2002


"Michele Simionato" <mis6 at pitt.edu> wrote in message
news:2259b0e2.0212111123.1e876e7f at posting.google.com...
> class C(object):
>       def m(self,x): return x*x
>       print 'type of m inside its class:',type(m)
>
> print 'type of C.m:', type(C.m)

> The output is
>
> type of m inside its class: <type 'function'>
> type of C.m: <type 'instance method'>
>
> i.e. the same object is seen as a function inside the class scope
and as an
> instance method outside the class scope. To me, this fact was quite
surprising,
> I don't like to have a changing type depending on the context.

Does the following 'changing type' surprise or bother you?

>>> a=1
>>> type(a)
<type 'int'>
>>> a=[a]
>>> type(a)
<type 'list'>

Your problem is your preconception/misunderstanding of class
construction and attribute access.  Its somewhat baroque.  Using id()
reveals the folowing:

>>> class demo:
...   def f(): pass
...   print id(f), type(f)
...
7958288 <type 'function'>
>>> print id(demo.f), type(demo.f)
7716912 <type 'instance method'>

The name 'f' is *not* (bound to) the same object in the two contexts,
any more than 'a' is in my snippet above (where the rebinding is more
obvious).  When a class statement is executed, the body (code) is
executed first, in a new namespace, *before* the class object exists.
Then the class name, bases tuple, and new namespace are passed as
arguments to the class constructor (its metatype or metaclass).  At
some point, the function is wrapped with an instance method object,
just as I wrapped an int with a list.  Introspecting just a bit more
reveals:

>>> dir(demo.f)
[...<standard attributes>... 'im_class', 'im_func', 'im_self']
>> id(demo.f.im_func), type(demo.f.im_func)
(7958288, <type 'function'>) # ie, this is original function
>>> demo == demo.f.im_class
1 #ie, method knows what class its a method of: it is not just a
function
# im_self is None here, but see below

At some point, its as if the following is  done:
  demo.f = instance_method(demo,f,None/instance)
But when?

>>> demo.__dict__['f']
<function f at 0x00796F10>
>>> 0x00796F10
7958288 #same as before
>>> print id(demo.f), type(demo.f)
7905904 <type 'instance method'> # new id!
>>> demo.f
<unbound method demo.f>
>>> d=demo()
>>> print id(d.f),type(d.f),d.f
7905904 <type 'instance method'> # id same  here, not always
>>> d.f
<bound method demo.f of <__main__.demo instance at 0x00794D00>>
>>> d.f.im_self
<__main__.demo instance at 0x00794D00>

So the rebinding happens magically upon access, with im_self being set
or not depending on the access path (via class or instance), and with
__repr__ also being slightly different.

Terry J. Reedy





More information about the Python-list mailing list