Re: Function mistaken for a method
On Thu, 01 Jun 2006 15:07:26 +0200, bruno at modulix <onurb@xiludom. gro>
wrote:[color=blue]
> Do yourself a favour : use new-style classes.
> class C(object)[/color]
I would if I could: I'm stuck with Python 2.1 for the moment (I should
have mentionned it; sorry for that).
[snip][color=blue][color=green]
>> Basically, I want an optional variant function across sub-classes of
>> the same class.
>>
>> I did it like in C1 for a start, then I needed
>> something like C2. The result is... surprising:
>>
>> 0
>> Traceback (most recent call last):
>> File "func-vs-meth.py", line 18, in ?
>> o2 = C2()
>> File "func-vs-meth.py", line 5, in __init__
>> self.x = self.f(0)
>> TypeError: <lambda>() takes exactly 1 argument (2 given)[/color]
>
> Not surprising at all.
>
> Functions implement the descriptor protocol[1]. When bound to a class
> and looked up via an instance, it's the __get__ method of the function
> object that get called - with the instance as param, as defined by the
> descriptor protocol. This method then return the function wrapped - with
> the instance - in an Method object - which itself, when called, returns
> the result of calling the function *with the instance as first
> parameter*. Which is how methods can work on the instance, and why one
> has to explicitly declare the instance parameter in "functions to be
> used as methods", but not explicitly pass it at call time.
>
> (please some guru correct me if I missed something here, but AFAIK it
> must be a correct enough description of method invocation mechanism in
> Python).
>
> [1] about descriptors, see:
> http://docs.python.org/ref/descriptors.html
> http://www.geocities.com/foetsch/pyt...tm#descriptors
>[color=green]
>> So the first works and o1.x is actually 0.[/color]
>
> int is not a function.[color=green][color=darkred]
>>>> type(int)[/color][/color]
> <type 'type'>
>
> int is a type.[/color]
Python 2.1 again:[color=blue][color=green][color=darkred]
>>> type(int)[/color][/color][/color]
<type 'builtin_functi on_or_method'>
But as someone mentionned, the problem is the same with other built-in
functions, such as chr, even in the latest Python version.
I still find that a little counter-intuitive to have different behaviours
for a built-in function and a Python function. I really would expect them
to work (or not to work) the same in all situations, even if I now
understand better how all works behind the scenes. But I'll live with it...
[snip][color=blue]
> If you understood all my explanations, you now know how to solve the
> problem.
>
> Else, here the solution:
>
> class C3(C):
> f = lambda self, x: return x[/color]
This is actually the first thing I did, but it seemed a bit weird to me to
have a - let's say - callable with one parameter in one case and another
with two parameters in the other one. So I finally turned my callable
attribute into a real instance method, just for consistency.
Anyway, thanks a lot for your explanations.
--
python -c "print ''.join([chr(154 - ord(c)) for c in
'U(17zX(%,5.zmz 5(17l8(%,5.Z*(9 3-965$l7+-'])"
On Thu, 01 Jun 2006 15:07:26 +0200, bruno at modulix <onurb@xiludom. gro>
wrote:[color=blue]
> Do yourself a favour : use new-style classes.
> class C(object)[/color]
I would if I could: I'm stuck with Python 2.1 for the moment (I should
have mentionned it; sorry for that).
[snip][color=blue][color=green]
>> Basically, I want an optional variant function across sub-classes of
>> the same class.
>>
>> I did it like in C1 for a start, then I needed
>> something like C2. The result is... surprising:
>>
>> 0
>> Traceback (most recent call last):
>> File "func-vs-meth.py", line 18, in ?
>> o2 = C2()
>> File "func-vs-meth.py", line 5, in __init__
>> self.x = self.f(0)
>> TypeError: <lambda>() takes exactly 1 argument (2 given)[/color]
>
> Not surprising at all.
>
> Functions implement the descriptor protocol[1]. When bound to a class
> and looked up via an instance, it's the __get__ method of the function
> object that get called - with the instance as param, as defined by the
> descriptor protocol. This method then return the function wrapped - with
> the instance - in an Method object - which itself, when called, returns
> the result of calling the function *with the instance as first
> parameter*. Which is how methods can work on the instance, and why one
> has to explicitly declare the instance parameter in "functions to be
> used as methods", but not explicitly pass it at call time.
>
> (please some guru correct me if I missed something here, but AFAIK it
> must be a correct enough description of method invocation mechanism in
> Python).
>
> [1] about descriptors, see:
> http://docs.python.org/ref/descriptors.html
> http://www.geocities.com/foetsch/pyt...tm#descriptors
>[color=green]
>> So the first works and o1.x is actually 0.[/color]
>
> int is not a function.[color=green][color=darkred]
>>>> type(int)[/color][/color]
> <type 'type'>
>
> int is a type.[/color]
Python 2.1 again:[color=blue][color=green][color=darkred]
>>> type(int)[/color][/color][/color]
<type 'builtin_functi on_or_method'>
But as someone mentionned, the problem is the same with other built-in
functions, such as chr, even in the latest Python version.
I still find that a little counter-intuitive to have different behaviours
for a built-in function and a Python function. I really would expect them
to work (or not to work) the same in all situations, even if I now
understand better how all works behind the scenes. But I'll live with it...
[snip][color=blue]
> If you understood all my explanations, you now know how to solve the
> problem.
>
> Else, here the solution:
>
> class C3(C):
> f = lambda self, x: return x[/color]
This is actually the first thing I did, but it seemed a bit weird to me to
have a - let's say - callable with one parameter in one case and another
with two parameters in the other one. So I finally turned my callable
attribute into a real instance method, just for consistency.
Anyway, thanks a lot for your explanations.
--
python -c "print ''.join([chr(154 - ord(c)) for c in
'U(17zX(%,5.zmz 5(17l8(%,5.Z*(9 3-965$l7+-'])"
Comment