Distinguishing attributes and methods

3 views
Skip to first unread message

tjh...@gmail.com

unread,
Dec 8, 2007, 2:19:40 AM12/8/07
to
Hi,

With properties, attributes and methods seem very similar. I was
wondering what techniques people use to give clues to end users as to
which 'things' are methods and which are attributes. With ipython, I
use tab completion all the time, but I can rarely tell from the names
alone whether it is an attribute or method.

Tips? Ideas? Best practices?

Here is one idea: Ipython should color-code the tab completion based
on attributes and methods.

Marc 'BlackJack' Rintsch

unread,
Dec 8, 2007, 3:10:32 AM12/8/07
to
On Fri, 07 Dec 2007 23:19:40 -0800, tjhnson wrote:

> With properties, attributes and methods seem very similar. I was
> wondering what techniques people use to give clues to end users as to
> which 'things' are methods and which are attributes.

Methods are attributes. So the decision is easy -- everything on an
object is an attribute. ;-)

Ciao,
Marc 'BlackJack' Rintsch

MonkeeSage

unread,
Dec 8, 2007, 3:34:06 AM12/8/07
to

I think he means callable attributes (methods) and non-callable
attributes (variables).

Regards,
Jordan

James Stroud

unread,
Dec 8, 2007, 6:50:40 AM12/8/07
to

Sure. Import types and test, then color code based on the test result.

For example:

py> import types
py> def doit(stuff):
... print stuff
...
py> class Thing(object):
... def amethod(self):
... print 42
...
py> t = Thing()
py> type(t.amethod) is types.MethodType
True
py> type(t.doit) is types.FunctionType
True
py> type(Thing.amethod) is types.UnboundMethodType
True
py> t.value = 4
py> type(t.value) not in (types.FunctionType, types.UnboundMethodType,
types.MethodType)
True


James

--
James Stroud
UCLA-DOE Institute for Genomics and Proteomics
Box 951570
Los Angeles, CA 90095

http://www.jamesstroud.com

Marc 'BlackJack' Rintsch

unread,
Dec 8, 2007, 7:50:05 AM12/8/07
to
On Sat, 08 Dec 2007 00:34:06 -0800, MonkeeSage wrote:

> I think he means callable attributes (methods) and non-callable
> attributes (variables).

But not every callable attribute is a method.

Ciao,
Marc 'BlackJack' Rintsch

MonkeeSage

unread,
Dec 8, 2007, 8:24:26 AM12/8/07
to

I swear, you dynamic programmers and your metaprogramming
tomfoolery! :P

Regards,
Jordan

Bruno Desthuilliers

unread,
Dec 8, 2007, 1:55:20 PM12/8/07
to
tjh...@gmail.com a écrit :

> Hi,
>
> With properties, attributes and methods seem very similar. I was
> wondering what techniques people use to give clues to end users as to
> which 'things' are methods and which are attributes.

Documentation.

> With ipython, I
> use tab completion all the time, but I can rarely tell from the names
> alone whether it is an attribute or method.

Actually, in Python, what you call "methods" are technically attributes
- usually class attributes, instances of the function class - until they
are looked up, at which time the lookup mechanism detect that they
implement the descriptor protocol, invoke it, an return the result of
this invocation - here a 'method' instance - in place of the original
attribute.

> Tips? Ideas? Best practices?

Reading the doc ?-)

Else, you can check whether the attribute is an instance of
types.MethodType - but that's not 100% garanteed to work (someone could
implement it's own descriptor type acting like a function but not
returning a method object).

Or if all you need to know is if the attribute is callable, then just ask:

print callable(obj.attr)

My 2 cents

Bruno Desthuilliers

unread,
Dec 8, 2007, 1:56:37 PM12/8/07
to
MonkeeSage a écrit :

callable attributes are not necessarily methods, and are still
'variables' anyway.

MonkeeSage

unread,
Dec 8, 2007, 2:44:36 PM12/8/07
to
On Dec 8, 12:56 pm, Bruno Desthuilliers

I think it muddies the water to say that a.a() and a.a are the same
thing--obviously they are not. In the common case, the first is a
method, and the second is a variable. Yes, you can do silly stuff,
such that this rule will not hold, but in general it does. Or am I
wrong?

Regards,
Jordan

Marc 'BlackJack' Rintsch

unread,
Dec 8, 2007, 3:36:56 PM12/8/07
to
On Sat, 08 Dec 2007 11:44:36 -0800, MonkeeSage wrote:

> On Dec 8, 12:56 pm, Bruno Desthuilliers

>> callable attributes are not necessarily methods, and are still
>> 'variables' anyway.
>
> I think it muddies the water to say that a.a() and a.a are the same
> thing--obviously they are not. In the common case, the first is a
> method, and the second is a variable.

No, the first is a call of `a.a` while the second is just referencing
`a.a`. And `a.a` is a "variable" no matter if it refers to a callable or
not. Variables are name to object bindings and methods are objects.

Ciao,
Marc 'BlackJack' Rintsch

Roberto Bonvallet

unread,
Dec 8, 2007, 3:45:46 PM12/8/07
to
On Dec 8, 4:19 am, tjhn...@gmail.com wrote:
> With properties, attributes and methods seem very similar. I was
> wondering what techniques people use to give clues to end users as to
> which 'things' are methods and which are attributes.

Methods are verbs, attributes are nouns :)

--
Roberto Bonvallet


Glenn Hutchings

unread,
Dec 8, 2007, 3:51:46 PM12/8/07
to
On Dec 8, 7:44 pm, MonkeeSage <MonkeeS...@gmail.com> wrote:
> I think it muddies the water to say that a.a() and a.a are the same
> thing--obviously they are not.

A thing is not what it is;
A thing is what it does.
This is the Way of the Duck.

-- Basho (in his "3 extra syllables" phase)

MonkeeSage

unread,
Dec 8, 2007, 4:07:27 PM12/8/07
to

Bah. Type-by-behavior never impressed me much. And I still think that
a.a is semantically different from a.a() in python.

Regards,
Jordan

Bruno Desthuilliers

unread,
Dec 8, 2007, 5:11:15 PM12/8/07
to
MonkeeSage a écrit :
> On Dec 8, 12:56 pm, Bruno Desthuilliers
> <bdesth.quelquech...@free.quelquepart.fr> wrote:
>
>>MonkeeSage a écrit :
>>
>>
>>
>>
>>>On Dec 8, 2:10 am, Marc 'BlackJack' Rintsch <bj_...@gmx.net> wrote:
>>
>>>>On Fri, 07 Dec 2007 23:19:40 -0800, tjhnson wrote:
>>
>>>>>With properties, attributes and methods seem very similar. I was
>>>>>wondering what techniques people use to give clues to end users as to
>>>>>which 'things' are methods and which are attributes.
>>
>>>>Methods are attributes. So the decision is easy -- everything on an
>>>>object is an attribute. ;-)
>>
>>>>Ciao,
>>>> Marc 'BlackJack' Rintsch
>>
>>>I think he means callable attributes (methods) and non-callable
>>>attributes (variables).
>>
>>callable attributes are not necessarily methods, and are still
>>'variables' anyway.
>
>
> I think it muddies the water to say that a.a() and a.a are the same
> thing--obviously they are not.

Indeed. a.a yields the object bound to name 'a' in object a, while a.a()
yields the value returned by calling the object bound to name 'a' in
object a.

> In the common case, the first is a
> method,

Nope, it's the value returned by the call to a callable - remember that
in Python, the parens are the call operator, so the expression a.a()
evals to the value returned by the call to a.a - which is either the
method object returned by the collaboration of the lookup mechanism and
the descriptor protocol or any other possible callable object bound to
that name or returned by the lookup mechanism for that name.

> and the second is a variable.

The second is whatever the lookup mechanism will yield for this name.

> Yes, you can do silly stuff,
> such that this rule will not hold, but in general it does. Or am I
> wrong?

You're wrong. Python's "methods" are thin wrappers around an instance
(or class) and a function. These wrappers are "built" *at lookup time*
by the __get__ method of the function object itself when it's looked up
as an attribute of a class, thanks to the lookup mechanism and the
descriptor protocol.

Now the fact that an attribute is callable doesn't make it a "method".

Also, anyone can implement it's own callable type that will act as a
true function - that is, implement the descriptor protocol to return a
wrapper around the instance or class and the callable - without
necessarily yielding an instance of types.MethodType. This is all fairly
trivial.

And note that none of the two above cases are necessarily "silly".
Python exposes most of it's object model so you can hook into it and
taylor it to your needs. This results in some constructs that may seem
weird at first, but make sens once you understand them and learn to use
them.

Bruno Desthuilliers

unread,
Dec 8, 2007, 5:16:43 PM12/8/07
to
MonkeeSage a écrit :

It is indeed and very obviously semantically different, and no one said
it wasn't. The first is an attribute lookup, the second is an attribute
lookup followed by a call. Now this doesn't make the attribute lookup
part different in both cases...

Roy Smith

unread,
Dec 8, 2007, 7:18:15 PM12/8/07
to
In article <475b17dc$0$31712$426a...@news.free.fr>,
Bruno Desthuilliers <bdesth.qu...@free.quelquepart.fr> wrote:

There are a very few corner cases were you can leave the ()'s out. For
example, you can do;

raise Exception

or

raise Exception()

but stuff like that is very much a wart in the language syntax.

Bruno Desthuilliers

unread,
Dec 9, 2007, 8:13:01 AM12/9/07
to
Roy Smith a écrit :

> In article <475b17dc$0$31712$426a...@news.free.fr>,
> Bruno Desthuilliers <bdesth.qu...@free.quelquepart.fr> wrote:
>
>
>>MonkeeSage a écrit :
(snip)

>>>Bah. Type-by-behavior never impressed me much. And I still think that
>>>a.a is semantically different from a.a() in python.
>>
>>It is indeed and very obviously semantically different, and no one said
>>it wasn't. The first is an attribute lookup, the second is an attribute
>>lookup followed by a call. Now this doesn't make the attribute lookup
>>part different in both cases...
>
>
> There are a very few corner cases were you can leave the ()'s out.

You can leave them out wherever you want - it's just that it won't do
the same thing !-)

> For
> example, you can do;
>
> raise Exception
>
> or
>
> raise Exception()

The context is somewhat different...

> but stuff like that is very much a wart in the language syntax.

The syntax is

raise [<expression>[, <expression>,[ <expression>]]]

which can be used as either

raise <type>[, <value>[, <traceback>]]

or

raise <instance>[, None[, <traceback>]]


http://docs.python.org/ref/raise.html

You can call it a wart, but at least it's a well defined one - that is,
the first expression must eval to either an Exception type or an
Exception instance. So the 'optional' use of the call operator here has
nothing to do with it's mandatory use to actually call a function.

MonkeeSage

unread,
Dec 9, 2007, 3:44:46 PM12/9/07
to
On Dec 8, 4:11 pm, Bruno Desthuilliers

You're talking about the result of calling a.a(), I'm talking about
what the attribute "a" on the object "a" is. Which is a callable
attribute, which by definition is called a "method" in the standard
sense [1]. You can make a distinction between a "method object" and
"any other possible callable object," but I wasn't using such a
distinction, I was using the standard definition. So my point holds.
When you see a.a(), because of pythons calling convention "()" you
know that "a" is a method of object "a".

The point is that just because the attributes are "looked up the same
way" or whatever, doesn't make them the same *kind* of attribute. To
say that all attributes are the same in python muddies the water. They
are the same in a generic sense that they are attributes, but not in
their particular qualities. Like saying "all humans are the same" --
yes, in a general sense of being human. But to leave it at that is not
very helpful.

[1] http://en.wikipedia.org/wiki/Method_%28computer_science%29

> > and the second is a variable.
>
> The second is whatever the lookup mechanism will yield for this name.
>
> > Yes, you can do silly stuff,
> > such that this rule will not hold, but in general it does. Or am I
> > wrong?
>
> You're wrong. Python's "methods" are thin wrappers around an instance
> (or class) and a function. These wrappers are "built" *at lookup time*
> by the __get__ method of the function object itself when it's looked up
> as an attribute of a class, thanks to the lookup mechanism and the
> descriptor protocol.
>
> Now the fact that an attribute is callable doesn't make it a "method".
>
> Also, anyone can implement it's own callable type that will act as a
> true function - that is, implement the descriptor protocol to return a
> wrapper around the instance or class and the callable - without
> necessarily yielding an instance of types.MethodType. This is all fairly
> trivial.

Again, I am using the common definition. I understand that you can
make an attribute callable in different ways than just the standard
machinery of "def symbol(self):" (those other techniques are what I
was referring to above by "metaprogramming"). But how it is made
callable doesn't matter (nor does how it is looked up). Once it is
callable, it fits the defintion of "method" I'm using. In future, I'll
try to be clear when I'm referring to something python specific or to
a general CS concept.

> And note that none of the two above cases are necessarily "silly".
> Python exposes most of it's object model so you can hook into it and
> taylor it to your needs. This results in some constructs that may seem
> weird at first, but make sens once you understand them and learn to use
> them.

"Silly" in the sense that in this context, they only serve to show
that TIMTOWTDI, but don't actually change a callable attribute from
being a callable attribute ("method" in the general CS sense) to being
some magical "something else". For the purpose of distinguishing an
object variable (non-callable attribute) and an object method
(callable attribute), they don't add anything.

Regards,
Jordan

Jan Claeys

unread,
Dec 9, 2007, 9:33:28 PM12/9/07
to
Op Sun, 09 Dec 2007 12:44:46 -0800, schreef MonkeeSage:

> The point is that just because the attributes are "looked up the same
> way" or whatever, doesn't make them the same *kind* of attribute. To say
> that all attributes are the same in python muddies the water. They are
> the same in a generic sense that they are attributes, but not in their
> particular qualities. Like saying "all humans are the same" -- yes, in a
> general sense of being human. But to leave it at that is not very
> helpful.

Well, I guess Python is a language for human being... ;-)


To conclude this discussion:

* in Python, methods are attributes
* in Ruby, attributes are methods


--
JanC

Steve Howell

unread,
Dec 9, 2007, 9:49:08 PM12/9/07
to Jan Claeys, pytho...@python.org

--- Jan Claeys <use...@janc.be> wrote:
>
> To conclude this discussion:
>
> * in Python, methods are attributes
> * in Ruby, attributes are methods
>

So clearly one of the languages has it all wrong. ;)


____________________________________________________________________________________
Never miss a thing. Make Yahoo your home page.
http://www.yahoo.com/r/hs

Marc 'BlackJack' Rintsch

unread,
Dec 10, 2007, 12:54:46 AM12/10/07
to
On Sun, 09 Dec 2007 12:44:46 -0800, MonkeeSage wrote:

> On Dec 8, 4:11 pm, Bruno Desthuilliers
> <bdesth.quelquech...@free.quelquepart.fr> wrote:
>> MonkeeSage a écrit :

> You're talking about the result of calling a.a(), I'm talking about
> what the attribute "a" on the object "a" is. Which is a callable
> attribute, which by definition is called a "method" in the standard
> sense [1]. You can make a distinction between a "method object" and
> "any other possible callable object," but I wasn't using such a
> distinction, I was using the standard definition. So my point holds.
> When you see a.a(), because of pythons calling convention "()" you
> know that "a" is a method of object "a".

No you don't know that. It's only a method of object `a` if it is really
a method bound to object `a` and not just a "data attribute" that happens
to be callable.

> Again, I am using the common definition. I understand that you can
> make an attribute callable in different ways than just the standard
> machinery of "def symbol(self):" (those other techniques are what I
> was referring to above by "metaprogramming"). But how it is made
> callable doesn't matter (nor does how it is looked up). Once it is
> callable, it fits the defintion of "method" I'm using. In future, I'll
> try to be clear when I'm referring to something python specific or to
> a general CS concept.

Your definition of "method" is a bit odd then. The general CS sense of
"method" requires the method to be bound to the object and not just be a
random callable. Let's see an example:

In [469]: a = collections.defaultdict(int)

In [470]: callable(a.default_factory)
Out[470]: True

In [471]: a.default_factory(42)
Out[471]: 42

`a.default_factory` is callable but hardly a method of `a` or `defaultdict`
but a "data attribute" that happens to be callable.

Ciao,
Marc 'BlackJack' Rintsch

Bruno Desthuilliers

unread,
Dec 10, 2007, 5:26:06 AM12/10/07
to
MonkeeSage a écrit :

> On Dec 8, 4:11 pm, Bruno Desthuilliers
(snip)

>>> I think it muddies the water to say that a.a() and a.a are the same
>>> thing--obviously they are not.
>> Indeed. a.a yields the object bound to name 'a' in object a, while a.a()
>> yields the value returned by calling the object bound to name 'a' in
>> object a.
>>
>>> In the common case, the first is a
>>> method,
>> Nope, it's the value returned by the call to a callable - remember that
>> in Python, the parens are the call operator, so the expression a.a()
>> evals to the value returned by the call to a.a - which is either the
>> method object returned by the collaboration of the lookup mechanism and
>> the descriptor protocol or any other possible callable object bound to
>> that name or returned by the lookup mechanism for that name.
>
> You're talking about the result of calling a.a()

No, I'm talking about the result of calling a.a - which is what a.a()
means !-)

Jordan, I of course understand what you mean - but the way you express
it is not coherent with how Python works. In Python, the expression
a.a() *is* the result of calling a.a, period.

>, I'm talking about
> what the attribute "a" on the object "a" is.

which is the value of expression "a.a". Whether this expression evals to
a callable object or not, and wether this callable object is actually a
method object or not is another question, mostly unrelated with the
meaning of expression 'a.a'.


> Which is a callable
> attribute, which by definition is called a "method" in the standard
> sense [1].

Still not. The fact that an attribute is callable doesn't make it a method.

> You can make a distinction between a "method object" and
> "any other possible callable object," but I wasn't using such a
> distinction, I was using the standard definition.

Which standard definition ? Obviously not Python's standard definition
anyway !-)

> So my point holds.
> When you see a.a(), because of pythons calling convention "()" you
> know that "a" is a method of object "a".

No you don't. You know that a.a is callable, period.

> The point is that just because the attributes are "looked up the same
> way" or whatever, doesn't make them the same *kind* of attribute.

<mode="stubborn">
Yes it does : they are all of kind 'object' !-)
</mode>

> To
> say that all attributes are the same in python muddies the water. They
> are the same in a generic sense that they are attributes, but not in
> their particular qualities.

Obviously not - but this is true for all known OOPL. Now from a
technical POV, there are no separate slots, no compiler-or-interpreter
special processing, nor nothing else special about 'methods', no special
type, etc - the storage and lookup mechanisms are *exactly* the same for
*all* attributes (leaving special features like __slots__ aside). All
the "magic" in 'methods' is handled by the way the function type
implements the descriptor protocol, and this can be reproduced by any
other type, because it's just *one* possible use of lookup hooks (+, in
this case, callable objects) - another possible use being the property
type. IOW, what makes the difference is the specific implementation of
the attribute's class, *not* the generic attribute storage/lookup mechanism.

> Like saying "all humans are the same" --
> yes, in a general sense of being human. But to leave it at that is not
> very helpful.
>
> [1] http://en.wikipedia.org/wiki/Method_%28computer_science%29

>>> and the second is a variable.
>> The second is whatever the lookup mechanism will yield for this name.
>>
>>> Yes, you can do silly stuff,
>>> such that this rule will not hold, but in general it does. Or am I
>>> wrong?
>> You're wrong. Python's "methods" are thin wrappers around an instance
>> (or class) and a function. These wrappers are "built" *at lookup time*
>> by the __get__ method of the function object itself when it's looked up
>> as an attribute of a class, thanks to the lookup mechanism and the
>> descriptor protocol.
>>
>> Now the fact that an attribute is callable doesn't make it a "method".
>>
>> Also, anyone can implement it's own callable type that will act as a
>> true function - that is, implement the descriptor protocol to return a
>> wrapper around the instance or class and the callable - without
>> necessarily yielding an instance of types.MethodType. This is all fairly
>> trivial.
>
> Again, I am using the common definition.

This "common definition" is obviously not applicable to each and every
language - at least when it comes to implementation !-)

Mays I remind you that the OP question was about "how to distinguish
methods from attributes". And the answer is that given Python's object
model and implementation, there's no clear, definitive and unambiguous
way to do so.

> I understand that you can
> make an attribute callable in different ways than just the standard
> machinery of "def symbol(self):" (those other techniques are what I
> was referring to above by "metaprogramming"). But how it is made
> callable doesn't matter (nor does how it is looked up).

The fact is that it does matter, because it's the lookup mechanism that
implements the hook used by functions to return methods when they are
used as class attributes. And it also matters because *all* this
behaviour can be reproduced without extending the function type nor
using the method type, so you can't even rely on typechecking to
distinguish a callable attribute from what is commonly known as a a method.

> Once it is
> callable, it fits the defintion of "method" I'm using.

Still not. May I remind you that the class is a callable attribute of an
object ? And that when used as *instance* attributes, functions remain
plain functions ? And that a class attribute can be callable without
implementing the lookup hook that would yield a method object ?

> In future, I'll
> try to be clear when I'm referring to something python specific or to
> a general CS concept.
>
>> And note that none of the two above cases are necessarily "silly".
>> Python exposes most of it's object model so you can hook into it and
>> taylor it to your needs. This results in some constructs that may seem
>> weird at first, but make sens once you understand them and learn to use
>> them.
>
> "Silly" in the sense that in this context, they only serve to show
> that TIMTOWTDI, but don't actually change a callable attribute from
> being a callable attribute ("method" in the general CS sense)

This is exactly what I'm trying to explain here : in Python, callable
attribute != method.

> to being
> some magical "something else".
> For the purpose of distinguishing an
> object variable (non-callable attribute) and an object method
> (callable attribute), they don't add anything.

By your definition, the class of an object is a method. I'll let you
think about it...

MonkeeSage

unread,
Dec 10, 2007, 6:56:10 AM12/10/07
to
It seems that I've got a short-circuit somewhere here. I understand
that everything is an object and the the storage/lookup system is
object-agnostic, and that it is only the descriptors (or "tags" as I
called them generically) that determine how an attribute is bound,
whether it is bound at all, whether it is even callable, and so forth.
So, when I say that all callable attributes (or to be more precise,
all callable attributes bound to objects other than toplevel) are
"methods," what am I missing?

You said "the difference [between a callable attribute and a method]
is the specific implementation of the attribute's class"...but this
almost sounds like type-by-primitive (a method is a method when it
derives from a certain base class), or type-by-behavior (a method is a
method when it behaves in a certain way, e.g., responds in a certain
way to a query). Is this correct? Shouldn't it be type-by-capability/
interface--i.e., it implements the protocol of a callable, therefore,
formally, it is not meaningfully different from any other callable
(quacks like a duck and all)?

I guess what I'm asking is, in what way is a "method" (or "function")
semantically different from a home-brewed callable I concoct and bind
to an object (or toplevel)? What is the distinction that I'm missing?

Ps. wrt your last comment, isn't a class object in essence a factory
method?

Regards,
Jordan

Bruno Desthuilliers

unread,
Dec 10, 2007, 8:19:38 AM12/10/07
to
MonkeeSage a écrit :

> It seems that I've got a short-circuit somewhere here. I understand
> that everything is an object and the the storage/lookup system is
> object-agnostic, and that it is only the descriptors (or "tags" as I
> called them generically)

"descriptor" is a protocol - an interface if you prefer. It's a way for
a class attribute to hook into the lookup mechanism, and it's
implemented by the property type - to provide a basic support for
computed attributes - and the function type - to provide the machinery
that turns a function into a method.

> that determine how an attribute is bound,
> whether it is bound at all, whether it is even callable,

An object is callable if it implement the __call__ method (for the
commonly admitted definition of 'method' !-).

> and so forth.
> So, when I say that all callable attributes (or to be more precise,
> all callable attributes bound to objects other than toplevel)

You mean "other than a module" ?

> are
> "methods," what am I missing?

All callable attributes that are either bound to an instance or don't
implement the descriptor protocol the way the function type do.

> You said "the difference [between a callable attribute and a method]
> is the specific implementation of the attribute's class"...but this
> almost sounds like type-by-primitive

It isn't.

> (a method is a method when it
> derives from a certain base class), or type-by-behavior (a method is a
> method when it behaves in a certain way, e.g., responds in a certain
> way to a query).

Bingo.

> Is this correct? Shouldn't it be type-by-capability/
> interface--i.e., it implements the protocol of a callable, therefore,
> formally, it is not meaningfully different from any other callable
> (quacks like a duck and all)?

The answer is in how the function type implements the descriptor
protocol. For an attribute to "become" a method when looked up, this
attribute has to implement the descriptor protocol so that it's __get__
method returns either a BoundMethod (or any equivalent) when looked up
on the instance and an UnboundMethod (or any equivalent) when looked up
on the class (I'll save you the details about classmethods etc).

Now since the method type is mostly trivial to implement, the fact that
an attribute lookup doesn't return an instance of Method doesn't
necessarily imply it's not one - so the truth is that an attribute is a
method if it behaves like one !-)

> I guess what I'm asking is, in what way is a "method" (or "function")

Python's 'methods' are really thin wrappers around an object, it's class
and a function. In the common use case, one of these wrappers is
instanciated each time you lookup a function that's a class attributes.

> semantically different from a home-brewed callable I concoct and bind
> to an object (or toplevel)? What is the distinction that I'm missing?

Implement your own callable that doesn't implement the descriptor
protocol, bind it to a class, instanciate your class, lookup this
attribute. You'll get the original attribute, not a method. Or bind a
function to an *instance*, and look it up - here again, you wont get a
method, but the original function object.

Now you can of course label this a static method if you want !-)

If you want a custom callable to be usable as a method, you have to
implement the descriptor protocol like the function type do.

> Ps. wrt your last comment, isn't a class object in essence a factory
> method?

Not quite - even if you can use it that way. In fact, the real factory
method is the __new__ method of the class - that is, the proper constructor.

A class object is an object that is responsible for:
* creating instances of itself (and as such, it is indeed a factory -
but a factory object, not a factory method)
* providing class attributes and mro to these instances (lookup rules
here: a name not found in the instance's __dict__ will be looked up in
the class, then in classes in the mro - unless of course the class
implements __getattr__ or __getattribute__, in which case all bets are
off).


caveat : all this describes the 'new-style' object model. The 'classic'
('old-style') object model works a bit differently.

> Regards,
> Jordan

Steven D'Aprano

unread,
Dec 10, 2007, 8:41:31 AM12/10/07
to
On Mon, 10 Dec 2007 03:56:10 -0800, MonkeeSage wrote:

> So, when I say that all callable attributes (or to be more precise, all
> callable attributes bound to objects other than toplevel) are "methods,"
> what am I missing?

Everything that isn't a method but is callable.

class Callable(object):
def __call__(self):
return oct(id(self))


class Foo(object):
aclass = type('Parrot', (object,), {})
atype = int
ainstance = Callable()
afunction = None # this is tricky...
def __init__(self): # a method
self.afunction = lambda n: n+1

--
Steven

MonkeeSage

unread,
Dec 10, 2007, 8:46:58 AM12/10/07
to
On Dec 10, 7:19 am, Bruno Desthuilliers <bruno.

Thank you kindly Bruno. You're answers have been very informative. I
thought I understand how python was operating, but I see that I have
some misconceptions. I honestly did read through the reference manual
when I started learning python a couple years ago, but I'm not the
most patient person by nature, and it seems that I was so happy with a
shiny new language, that I imported some foreign concepts into the
picture and glossed over many of the details of pythons object model.
I'm going to give the "Data Model" section a thorough going-over
again, and try to pay more attention this time(!) ;)

Just as a side-note, it's interesting that even through my
misunderstandings I've been able to use python to great effect (I've
translated several fairly complex apps to python, using decorators,
CPS and other fairly "advanced" techniques, and it "Just Worked").
Heh. Nice language. :)

Anyway, thanks again for your time an patience.

Regards,
Jordan

Bruno Desthuilliers

unread,
Dec 10, 2007, 9:11:13 AM12/10/07
to
MonkeeSage a écrit :

> On Dec 10, 7:19 am, Bruno Desthuilliers <bruno.
(snip)

> I'm going to give the "Data Model" section a thorough going-over
> again, and try to pay more attention this time(!) ;)

Also make sure you read the docs about new-style classes, the descriptor
protocol and metaclasses.

> Just as a side-note, it's interesting that even through my
> misunderstandings I've been able to use python to great effect (I've
> translated several fairly complex apps to python, using decorators,
> CPS and other fairly "advanced" techniques, and it "Just Worked").
> Heh. Nice language. :)

Indeed !-)

> Anyway, thanks again for your time an patience.

Thanks *you* for your patience - I'm certainly not the best teacher here !-)

Bruno Desthuilliers

unread,
Dec 10, 2007, 1:58:15 PM12/10/07
to
Jan Claeys a écrit :
And this is probably the most sensible post in this thread !-)

Bruno Desthuilliers

unread,
Dec 10, 2007, 2:03:37 PM12/10/07
to
Steve Howell a écrit :

> --- Jan Claeys <use...@janc.be> wrote:
>
>>To conclude this discussion:
>>
>> * in Python, methods are attributes
>> * in Ruby, attributes are methods
>>
>
>
> So clearly one of the languages has it all wrong. ;)
>

Nope, quite on the contrary, both got it right !-)

Florian Diesch

unread,
Dec 11, 2007, 8:09:35 PM12/11/07
to
MonkeeSage <Monke...@gmail.com> wrote:

--8<---------------cut here---------------start------------->8---
#!/usr/bin/env python

class Foo(object):

def __init__(self):
def func(*args):
return str(args)
self.a=func

def b(*args):
return str(args)

@classmethod
def c(*args):
return str(args)

f=Foo()
print f.a(1) # just a callble
print f.b(1) # an instance method
print f.c(1) # a class method
--8<---------------cut here---------------end--------------->8---

Florian
--
<http://www.florian-diesch.de/>
-----------------------------------------------------------------------
** Hi! I'm a signature virus! Copy me into your signature, please! **
-----------------------------------------------------------------------

Boris Borcic

unread,
Dec 19, 2007, 8:28:59 AM12/19/07
to pytho...@python.org
MonkeeSage wrote:
> what am I missing?

To my eyes, when you write:

>I think it muddies the water to say that a.a() and a.a are the same

>thing--obviously they are not. In the common case, the first is a
>method, and the second is a variable.

What you are most obviously missing is what's shown by

b=a.a
b()

IOW I am tempted to make the prediction that you never use bound methods as
values :)

Cheers, BB

Reply all
Reply to author
Forward
0 new messages