Distinguishing attributes and methods

Bruno Desthuilliers bruno.42.desthuilliers at wtf.websiteburo.oops.com
Mon Dec 10 05:26:06 EST 2007


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...



More information about the Python-list mailing list