class objects, method objects, function objects

7

7stud

Hi,

I'm trying to figure out what this passage from GvR's tutorial means:
-------
Class definitions, like function definitions (def statements) must be
executed before they have any effect....

When a class definition is entered, a new namespace is created...

When a class definition is left normally (via the end), a class object
is created.

If you still don't understand how methods work, a look at the
implementation can perhaps clarify matters. When an instance attribute
is referenced that isn't a data attribute, its class is searched. If
the name denotes a valid class attribute that is a function object, a
method object is created by packing (pointers to) the instance object
and the function object just found together in an abstract object:
this is the method object.
-----------

Here is my diagram of the above:

class object
----------------------------------------
| class MyClass: |
| def __init__(self): |
| self.name = "GvR" |
| def sayHi(self): |
| print "Hello " + self.name |
|________________________________________|


x = MyClass()
x.sayHi() #the "class search" begins which initiates the
#creation of the method object:


method object instance object
----------------- --------------
| ptr1 ----------|--------> |x = MyClass() |
| ptr2 | |______________|
| | |
|___|_____________|
|
|
V
function object
---------------------------------
| def sayHi(self): print "hello" |
|_________________________________|

But the last part of the passage makes no sense to me:
 
7

7stud

Oops, here is that last sentence in context(section 9.3.4):
------------
What exactly happens when a method is called? You may have noticed
that x.f() was called without an argument above, even though the
function definition for f specified an argument. What happened to the
argument? Surely Python raises an exception when a function that
requires an argument is called without any -- even if the argument
isn't actually used...

Actually, you may have guessed the answer: the special thing about
methods is that the object is passed as the first argument of the
function. In our example, the call x.f() is exactly equivalent to
MyClass.f(x). In general, calling a method with a list of n arguments
is equivalent to calling the corresponding function with an argument
list that is created by inserting the method's object before the first
argument.

If you still don't understand how methods work, a look at the
implementation can perhaps clarify matters. When an instance attribute
is referenced that isn't a data attribute, its class is searched. If
the name denotes a valid class attribute that is a function object, a
method object is created by packing (pointers to) the instance object
and the function object just found together in an abstract object:
this is the method object. When the method object is called with an
argument list, it is unpacked again, a new argument list is
constructed from the instance object and the original argument list,
and the function object is called with this new argument list.
------------
 
7

7stud

Darn. I made some changes to the class and I didn't change the
function object. It should be:

|
V
function object
---------------------------------
| def sayHi(self): |
| print "Hello " + self.name|
|_________________________________|
 
G

Gabriel Genellina

But the last part of the passage makes no sense to me:
------
When the method object is called with an argument list, it is unpacked
again, a new argument list is constructed from the instance object and
the original argument list, and the function object is called with
this new argument list.

Calling a.foo(x,y) means that, after fetching foo from a, a new argument
list must be constructed containing 3 items: the instance a (self), x and
y.
 
A

Alex Martelli

7stud said:
But the last part of the passage makes no sense to me:
------
When the method object is called with an argument list, it is unpacked
again, a new argument list is constructed from the instance object and
the original argument list, and the function object is called with
this new argument list.

Here's the Python pseudocode equivalent...

class Method(object):
def __init__(self, im_func, im_self):
self.im_func = im_func
self.im_self = im_self
def __call__(self, *a, **k):
return self.im_func(self.im_self, *a, **k)

Whenever you get foo.somemeth from an instance foo of whatever class
(with somemeth being a method of that class), you obtain the equivalent
of a Method(type(foo).__dict__('somemeth'), foo) in the above
pseudocode. When you call that foo.somemeth, the im_self (i.e., foo) is
prepended to other positional arguments (if any).

This, btw, takes place in the __get__ method of the function object
somemeth -- function objects are descriptors, i.e., they have __get__
methods, and that's just what they do.

If this is still a bit obscure to you, perhaps more practice with Python
may be needed before you dwell into the internals of methods &c.


Alex
 
F

Fredrik Lundh

7stud said:
But the last part of the passage makes no sense to me:
------
When the method object is called with an argument list, it is unpacked
again, a new argument list is constructed from the instance object and
the original argument list, and the function object is called with
this new argument list.

when you call obj.method(arg1, arg2), Python prepends the actual instance
object (obj) to the argument list, so you end up calling (obj.method) with the
arguments (obj, arg1, arg2).

</F>
 
7

7stud

Hi,

Thanks for the responses. I understand that python automatically
sends 'self' to a member function, i.e. self gets prepended to the
argument list. I guess I am having trouble with this statement:
----
When the method object is called with an
argument list, it is unpacked again, a new argument list is
constructed from the instance object and the original argument list,
and the function object is called with this new argument list.
---
because I don't quite understand the timing. The "unpacked again"
part confuses me. If I have this code:

class MyClass:
def g(self, name):
print "Hello " + name

x = MyClass()
x.g("GvR")

here is what happens when I try to follow the sequence of events GvR
describes:
----------------
When an instance attribute is referenced that isn't a data attribute,
its class is searched.

x.g("GvR") ==> 'g' is not a data attribute, so class is searched.

If the name denotes a valid class attribute that is a function object,
a
method object is created by packing (pointers to) the instance object
and the function object just found together in an abstract object:
this is the method object.

==>method object is created

When the method object is called with an
argument list,

x.g("GvR") ==> I think I'm both "referencing an instance attribute"
and calling the method object with an argument list

it(the method object) is unpacked again, a new argument list is
constructed from the instance object and the original argument list,
and the function object is called with this new argument list.

??
 
D

Duncan Booth

7stud said:
When the method object is called with an
argument list,

x.g("GvR") ==> I think I'm both "referencing an instance attribute"
and calling the method object with an argument list

it(the method object) is unpacked again, a new argument list is
constructed from the instance object and the original argument list,
and the function object is called with this new argument list.

It may help you to understand if you consider the two parts separately.
There is no linkage between 'referencing an instance attribute' and
'calling the method object'. You can rewrite the code as:

method = x.g
method("GvR")

and it works in exactly the same way. First you reference the attribute
'x.g', which looks up MyClass.g (an unbound method) and calls
MyClass.g.__get__(x, MyClass) which creates a new bound method. Then you
call the bound method passing "GvR" as the first positional argument: so a
single element tuple is created for the argument list.

The bound method object unpacks and repacks the tuple to give the two-tuple
(self, "GvR") which it then passes to the original function.
 
D

Dennis Lee Bieber

Hi,

Thanks for the responses. I understand that python automatically
sends 'self' to a member function, i.e. self gets prepended to the
argument list. I guess I am having trouble with this statement:
----
When the method object is called with an
argument list, it is unpacked again, a new argument list is
constructed from the instance object and the original argument list,
and the function object is called with this new argument list.
said:
it(the method object) is unpacked again, a new argument list is

"it(the" -- argument list, not the object -- ") is unpacked again, a
new argument list is constructed from the instance object" (ie, the
object is turned into the first argument 'self') "and the original
argument list..."


object.method(arg, u, ments) is turned into

class_function(object, arg, u, ments)


Would be how /I/ read the documents.

--
Wulfraed Dennis Lee Bieber KD6MOG
(e-mail address removed) (e-mail address removed)
HTTP://wlfraed.home.netcom.com/
(Bestiaria Support Staff: (e-mail address removed))
HTTP://www.bestiaria.com/
 
F

Fredrik Lundh

Dennis said:
"it(the" -- argument list, not the object -- ") is unpacked again

no, "it" refers to the bound method object, as 7stud would have realized if
he'd read the entire paragraph. here's the relevant portion:

/.../ a method object is created by packing (pointers to) the instance object
and the function object just found together in an abstract object: this is the
method object. When the method object is called with an argument list, it
is unpacked again /.../

</F>
 
D

Dennis Lee Bieber

no, "it" refers to the bound method object, as 7stud would have realized if
he'd read the entire paragraph. here's the relevant portion:

/.../ a method object is created by packing (pointers to) the instance object
and the function object just found together in an abstract object: this is the
method object. When the method object is called with an argument list, it
is unpacked again /.../
Ah, one level more of indirection (in understanding, not code
pointers)... At least, it now reads like...

instance.method(argu, ments)

-> (instance, class_function)(argu, ments)

-> class_function(instance, argu, ments)
--
Wulfraed Dennis Lee Bieber KD6MOG
(e-mail address removed) (e-mail address removed)
HTTP://wlfraed.home.netcom.com/
(Bestiaria Support Staff: (e-mail address removed))
HTTP://www.bestiaria.com/
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,733
Messages
2,569,440
Members
44,832
Latest member
GlennSmall

Latest Threads

Top