Method / Functions - What are the differences?

M

Michael Rudolf

Out of curiosity I tried this and it actually worked as expected:
x=[]
foo=x.append
def f(self):
return self.x

>>> t=T()
>>> t.f() []
>>> T.foo(1)
>>> t.f() [1]
>>>

At first I thought "hehe, always fun to play around with python. Might
be useful sometimes" - but then It really confused me what I did. I
mean: f is what we call a method, right? But was is foo? It is not a
method and not a classmethod as it accepts no self and no cls.
So that leaves staticmethod? OK, fair, as x is "static" here anyway this
reflects what it does. But then consider this:
def __init__(self):
self.x=[]
self.foo=self.x.append
def f(self):
return self.x

>>> y=T()
>>> y.x []
>>> y.foo(1)
>>> y.x [1]
>>> a=T()
>>> a.x []
>>> a.foo(2)
>>> a.x [2]
>>>

Note that all I did was moving the list and foo into the instance. Still
no self and no cls, but also no static behaviour any more.

So is foo just nothing of the above and really only a class/instance
attribute which happens to be callable?

Perhaps this all does not matter, but now I am really confused about the
terminology. So: what makes a method a method? And of what type?

Regards,
Michael
 
A

Alf P. Steinbach

* Michael Rudolf:
Out of curiosity I tried this and it actually worked as expected:
x=[]
foo=x.append
def f(self):
return self.x

t=T()
t.f() []
T.foo(1)
t.f() [1]

At first I thought "hehe, always fun to play around with python. Might
be useful sometimes" - but then It really confused me what I did. I
mean: f is what we call a method, right? But was is foo?

foo is (refers to) an object that supports call notation and that forwards calls
somewhere else, in this case to append on a list.

You might call it (descriptive) a call forwarder, or (C# or general terminology)
a delegate, or (Python 2.x) a bound method.


S.upper() -> str

Return a copy of S converted to uppercase.</example>


A common use for delegates is as command handlers in a GUI application, and in
general for event notifications.


Cheers & hth.,

- Alf
 
M

Michael Rudolf

Am 28.02.2010 15:08, schrieb Alf P. Steinbach:

Holy hand grenade.
You have no Idea how enlightened I feel right now :D

Thank you, "bound method" was the term I forgot and your example...
....totally revealed the internals behind this to me. Especially the last
line I quoted.
I mean, I always knew *that* this works, but I never knew *why*.

Regards,
Michael
 
B

Bruno Desthuilliers

Michael Rudolf a écrit :
Out of curiosity I tried this and it actually worked as expected:
x=[]
foo=x.append
def f(self):
return self.x

t=T()
t.f() []
T.foo(1)
t.f() [1]

At first I thought "hehe, always fun to play around with python. Might
be useful sometimes" - but then It really confused me what I did. I
mean: f is what we call a method, right?

Wrong. It's a function. T.f is an unbound method (in python 2.x at
least) and t.f is a bound method.
But was is foo?

A bound method. Bound to x, of course.
It is not a
method and not a classmethod as it accepts no self and no cls.

Yes it does. Else how would t.foo(4) (or T.foo(4)) append 4 to x ?
Perhaps this all does not matter,

It does.
but now I am really confused about the
terminology. So: what makes a method a method?

The right question is: what makes a function a method !-)
And of what type?

Answer here:

http://groups.google.com/group/comp...022765c/3a77541bf9d6617d#doc_89d608d0854dada0

I really have to put this in the wiki :-/
 
J

John Posner



Bruno, I performed a light copy-edit of your writeup and put in some
reStructuredText (reST) markup. The result is at:

http://cl1p.net/bruno_0301.rst/

The only sentence that I think needs work is:

Having access to itself (of course), the
instance (if there's one) and the class, it's easy for it
to wrap all this into a **method** object.

Maybe this?

With the instance object (if any) and class object available,
it's easy to create a method object that wraps the function object.


Begging pardon for my presumptuousness,
John
 
B

Bruno Desthuilliers

John Posner a écrit :
Bruno, I performed a light copy-edit of your writeup and put in some
reStructuredText (reST) markup. The result is at:

http://cl1p.net/bruno_0301.rst/
Cool.


The only sentence that I think needs work is:

Having access to itself (of course), the
instance (if there's one) and the class, it's easy for it
to wrap all this into a **method** object.

Maybe this?

With the instance object (if any) and class object available,
it's easy to create a method object that wraps the function object.

That's perfect.

But there's also a typo to fix in the Python implementation of the
Method object: in the call method, it should inject self.im_self as
first arg, not self.im_func. This had been spotted by someone named John
Posner, IIRC !-)

Begging pardon for my presumptuousness,

Begging pardon for my laziness :-/
 
J

John Posner

That's perfect.

Fixed.

But there's also a typo to fix in the Python implementation of the
Method object: in the call method, it should inject self.im_self as
first arg, not self.im_func. This had been spotted by someone named John
Posner, IIRC !-)


Fixed (oops!).

I've updated the text at this location:

I think the ball is back in your court, Bruno. I'd be happy to help more
-- feel free to contact me off-list, at (e-mail address removed).

Best,
John
 
E

Eike Welk

John said:
I've updated the text at this location:

I think this is a very useful writeup!

It would be perfect with a little bit of introduction that says:
1. - What it is: "The rough details of method look-up";
2. - which contains some of the questions that that made that authors write
the text. This way people with similar questions can find it with Google.

Additionally the link to the relevant section in the Python documentation
would be great. I can't find it!

A link to an article about the details of class creation and metaclasses
would be good too.


Thanks for writing this great little text,
Eike.
 
B

Bruno Desthuilliers

Eike Welk a écrit :
I think this is a very useful writeup!

It would be perfect with a little bit of introduction that says:
1. - What it is: "The rough details of method look-up";
2. - which contains some of the questions that that made that authors write
the text. This way people with similar questions can find it with Google.

John, do you think you could something with the following ?

"""
"Is it a function ? is it a method ? No, it's... " - or : What's in a
Python method ?

Python newcomers often have hard time understanding the "magic" behind
Python's methods - and truth is that Python's object model can be a bit
peculiar when compared to most mainstream (or not-so-mainstream) OOPLs.
As a matter of fact, there are quite a few threads on c.l.py with either
direct or indirect questions about what makes a Python method, and I
must have explained the whole mechanism at least 3 or 4 times there. The
following text is an edited version of my last attempt, as edited,
corrected and published by John Posner, MayHisNameBePraised(tm).

This text isn't meant as a replacement for neither the official
FineManual(tm)[XXX : relevant link] nor the very excellent - if somehow
technical - 'Descriptors how-to' [XXX : relevant link]. It's mostly a
brief but hopefully helpful overview of what exactly is a Python method,
and how Python magically inserts the 'self' or 'cls' argument to method
calls.
"""

Feel free to edit / amend / rewrite / trash at will - you're now
officially in charge of publishing this text !-)
 
J

John Posner

Eike Welk a écrit :

John, do you think you could something with the following ?

Sure thing, Bruno. I'll incorporate/edit your new text below into a
Python Wiki entry. The headings in the Documentation table of contents
page (http://wiki.python.org/moin/Documentation) seem pretty sober, so I
plan to use a straightforward title:

FromFunctionsToMethods

.... instead of the clearly superior ...

ItsAFunctionItsAMethodItsAUseOfTheDescriptorProtocol

Does this article belong in the "Advanced Topics" section of the page?
I'm not sure, but I'll place it there for now. (Alternative suggestions
welcome!)
"""
"Is it a function ? is it a method ? No, it's... " - or : What's in a
Python method ?

Python newcomers often have hard time understanding the "magic" behind
Python's methods - and truth is that Python's object model can be a bit
peculiar when compared to most mainstream (or not-so-mainstream) OOPLs.
As a matter of fact, there are quite a few threads on c.l.py with either
direct or indirect questions about what makes a Python method, and I
must have explained the whole mechanism at least 3 or 4 times there. The
following text is an edited version of my last attempt, as edited,
corrected and published by John Posner, MayHisNameBePraised(tm).

This text isn't meant as a replacement for neither the official
FineManual(tm)[XXX : relevant link] nor the very excellent - if somehow
technical - 'Descriptors how-to' [XXX : relevant link]. It's mostly a
brief but hopefully helpful overview of what exactly is a Python method,
and how Python magically inserts the 'self' or 'cls' argument to method
calls.
"""

Feel free to edit / amend / rewrite / trash at will - you're now
officially in charge of publishing this text !-)

Yow, the mantle of responsibility weighs heavily upon my poor shoulders!

Film at 11,
John
 
B

Bruno Desthuilliers

John Posner a écrit :
Sure thing, Bruno. I'll incorporate/edit your new text below into a
Python Wiki entry. The headings in the Documentation table of contents
page (http://wiki.python.org/moin/Documentation) seem pretty sober, so I
plan to use a straightforward title:

FromFunctionsToMethods

What about "TheMagicBehindMethods" ? Mmm, not sure, so do what you think
is best.
... instead of the clearly superior ...

ItsAFunctionItsAMethodItsAUseOfTheDescriptorProtocol

Does this article belong in the "Advanced Topics" section of the page?
I'm not sure, but I'll place it there for now. (Alternative suggestions
welcome!)

I spotted this:

http://www.python.org/doc/faq/programming/#what-is-a-method
http://www.python.org/doc/faq/gener...ed-explicitly-in-method-definitions-and-calls

Our text is probably a bit too long for a direct inclusion in the FAQ,
so I'd say it should go in the AdvancedTopics, and be linked from the FAQ.
Yow, the mantle of responsibility weighs heavily upon my poor shoulders!

!-)


Thanks for doing the grunt work.
 
J

John Posner

I spotted this:

http://www.python.org/doc/faq/programming/#what-is-a-method
http://www.python.org/doc/faq/gener...ed-explicitly-in-method-definitions-and-calls


Our text is probably a bit too long for a direct inclusion in the FAQ,
so I'd say it should go in the AdvancedTopics, and be linked from the FAQ.

Linking from the FAQ means changing the official Python documentation,
which requires lots of hoop-jumping-through. I suggest that we content
ourselves with using the Wiki -- at least for now.
Thanks for doing the grunt work.

Pas de quoi.

-John
 
E

Eike Welk

Bruno said:
John Posner a écrit :

Done and well done !-)
Thanks again for the good job John.

I like it too, thanks to both of you!

I have two small ideas for improvement:
- Swap the first two paragraphs. First say what it is, and then give the
motivation.
- The section about the descriptor protocol is a bit difficult to
understand. But judging from the official descriptor documentation, it seems
to be hard to explain: The official documentation is nearly incomprehensible
(IMHO).
 
J

John Posner

I have two small ideas for improvement:
- Swap the first two paragraphs. First say what it is, and then give the
motivation.

No problem -- since this is a Wiki, you can perform the swap yourself!
(If you haven't done it in a day or so, I'll do the deed.)
- The section about the descriptor protocol is a bit difficult to
understand. But judging from the official descriptor documentation, it seems
to be hard to explain: The official documentation is nearly incomprehensible
(IMHO).

I empathize -- it took me a while to grok descriptors. I was thinking
today about "doing a Bruno", and producing similar pieces on:

* properties created with the @property decorator

* the descriptor protocol

I'll try to produce something over the next couple of days.

-John
 
B

Bruno Desthuilliers

Eike Welk a écrit :
I like it too, thanks to both of you!

I have two small ideas for improvement:
- Swap the first two paragraphs. First say what it is, and then give the
motivation.

Mmm... As far as I'm concerned, I like it the way its. John ?
- The section about the descriptor protocol is a bit difficult to
understand.

I may eventually try to rework it a bit when I'll have time (death march
here currently, duh...)
But judging from the official descriptor documentation, it seems
to be hard to explain

Not that easy, indeed. I once posted on c.l.py a longer explanation of
the whole lookup rule stuff, that IIRC included a "naive python
implementation" example. Might be worth trying to google for it and
turning it into another "overview" article.
: The official documentation is nearly incomprehensible
(IMHO).

I should probably have a look at it !-)
 
J

John Posner

Mmm... As far as I'm concerned, I like it the way its. John ?

I think it doesn't make very much difference. But in the end, I believe
it's the student, not the teacher, who gets to decide what's comprehensible.

What *does* make a difference, IMHO, is getting more people to
participate in the process of shining lights into Python's darker
corners. That's why I encouraged (and still encourage) Eike to roll up
the sleeves and wade into these waters.

Metaphor-mixingly yours,
John
 
J

John Posner

... I was thinking
today about "doing a Bruno", and producing similar pieces on:

* properties created with the @property decorator

* the descriptor protocol

I'll try to produce something over the next couple of days.

Starting to think about a writeup on Python properties, I've discovered
that the official Glossary [1] lacks an entry for "property" -- it's
missing in both Py2 and Py3!

Here's a somewhat long-winded definition -- comments, please:

---------------------------------------------
An attribute, *a*, of an object, *obj*, is said to be implemented as a
property if the standard ways of accessing the attribute:

* evaluation: print obj.a
* assignment: obj.a = 42
* deletion: del obj.a

.... cause methods of a user-defined *property object* to be invoked. The
attribute is created as a class attribute, not an instance attribute.
Example:

class Widget:
# create "color" as class attribute, not within __init__()
color = <<property-object>>

def __init__(self, ...):
# do not define "self.color" instance attribute

The property object can be created with the built-in function
property(), which in some cases can be coded as a decorator: @property.
The property object can also be an instance of a class that implements
the descriptor protocol.
---------------------------------------------

Tx,
John

[1] http://docs.python.org/glossary.html
 
B

Bruno Desthuilliers

John Posner a écrit :
... I was thinking
today about "doing a Bruno", and producing similar pieces on:

* properties created with the @property decorator

* the descriptor protocol

I'll try to produce something over the next couple of days.

Starting to think about a writeup on Python properties, I've discovered
that the official Glossary [1] lacks an entry for "property" -- it's
missing in both Py2 and Py3!

Here's a somewhat long-winded definition -- comments, please:

---------------------------------------------
An attribute, *a*, of an object, *obj*, is said to be implemented as a
property if the standard ways of accessing the attribute:

* evaluation: print obj.a
* assignment: obj.a = 42
* deletion: del obj.a

... cause methods of a user-defined *property object* to be invoked.

Hmmm... a couple remarks:

1/ "property" is actually the name of a Python builtin type. It's also
pretty much used in general OO litterature for what we name
"attributes". So I think it would be better to avoid confusion between
"property" as the builtin type, "property" as synonym for attribute, and
"property" as the more specific concept of "computed attribute" - which
is what you're describing here.

As far as I'm concerned, I prefer to stick to "computed attribute" for
the generic case, and only use "property" when the computed attribute is
actually implemented using the builtin property type.

2/ depending on how the computed attribute is implemented, the
computation needs not happen on ALL get/set/del access - you can have
non-binding descriptors (that is, not implementing __set__).

Also, the "standard" access also include getattr(), setattr() and
delattr() (might be worth a note).
The
attribute

/attribute/user-defined object/ here ?
is created as a class attribute, not an instance attribute.
Example:

class Widget:
# create "color" as class attribute, not within __init__()
color = <<property-object>>

def __init__(self, ...):
# do not define "self.color" instance attribute

Yes you can, and it's even actually pretty common:

# example.py
from somewhere import RGBColor

class Foo(object):
def _get_color(self):
return str(self._color)
def _set_color(self, val):
self._color = RGBColor.from_string(val)
color = property(fget=_get_color, fset=_set_color)

def __init__(self, colorvalue):
self.color = colorvalue

The property object can be created with the built-in function
property(),

It's actually a type, not a function.
which in some cases can be coded as a decorator: @property.
The property object can also be an instance of a class that implements
the descriptor protocol.

The "property object" IS an instance of a class that implements the
descriptor protocol. The property type is just a "generic" descriptor:

# naive (and incomplete) python implementation of the property type

class property(object):
def __init__(self, fget, fset=None, fdel=None)
self._fget = fget
self._fset = fset
self._fdel = fdel

def __get__(self, instance, cls):
if instance is None:
return self
return self._fget(instance)

def __set__(self, instance, value):
if not self._fset:
raise AttributeError("can't set attribute")
self._fset(instance, value)

def __del__(self):
if not self._fdel:
raise AttributeError("can't delete attribute")
self._fdel(instance)


As far as I'm concerned, I'd "plan" such a paper as:

"""
What's a property ? It's a computed attribute implemented using the
builtin "property" type.

Ok, so far it doesn't help much. So
1/ what's a computed attribute, and
2/ what is the property type ?

1/ your above explanation about what's a computed attribute in general,
then a brief explanation of how computed attributes are implemented in
python -> IOW, the descriptor protocol

2/ my above snippet !-)

"""

I think the way you started explaining computed attributes wrt/
attribute access could be a pretty good way to explain the descriptor
protocol, since the mapping from get/set/del access to __get__, __set__,
and __del__ magic methods is then pretty obvious.

But YMMV of course, so by all mean feel free to discard all or parts of
the above remarks !-)

HTH
 

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

Forum statistics

Threads
473,995
Messages
2,570,235
Members
46,821
Latest member
AleidaSchi

Latest Threads

Top