Hi all,
I just stepped on a thing that I can't explain. Here is some code showing
the problem:
-----------------------------
class C:
f = None
def __init__(self):
if self.f is not None:
self.x = self.f(0)
else:
self.x = 0
class C1(C):
f = int
class C2(C):
f = lambda x: x != 0
o1 = C1()
print o1.x
o2 = C2()
print o2.x
-----------------------------
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)
So the first works and o1.x is actually 0. But the second fails because
self is also being passed as the first argument to the lambda. Defining a
"real" function doesn't help: the error is the same.
My actual question is: why does it work in one case and not in the other?
As I see it, int is just a function with one parameter, and the lambda is
just another one. So why does the first work, and not the second? What
'black magic' takes place so that int is not mistaken for a method in the
first case?
--
python -c "print ''.join([chr(154 - ord(c)) for c in
'U(17zX(%,5.zmz5(17l8(%,5.Z*(93-965$l7+-'])" 17 2203
Le Jeudi 01 Juin 2006 13:12, Eric Brunel a écrit : class C1(C): f = int
int is not a function but a type, but it's callable so int(0) return 0.
class C2(C): f = lambda x: x != 0
lambda is a function, applied as a class attribute it becomes a method so it's
called with a first parameter representing the instance, self.f(0) in the
__init__ becomes C2.f(self, 0), so the lambda should be :
f = lambda s, x: x != 0 # s for self, some poeple use _
this exactly the same as :
def f(self, val) :
return x != 0
(that lambda will return True or False i expect this is not what you want)
--
_____________
Maric Michaud
_____________
Aristote - www.aristote.info
3 place des tapis
69004 Lyon
Tel: +33 426 880 097
Le Jeudi 01 Juin 2006 13:29, Maric Michaud a écrit*: this exactly the same as :
* *def f(self, val) : * * * *return x != 0
oops,
def f(self, val) :
return val != 0
--
_____________
Maric Michaud
_____________
Aristote - www.aristote.info
3 place des tapis
69004 Lyon
Tel: +33 426 880 097
Eric Brunel wrote: My actual question is: why does it work in one case and not in the other? As I see it, int is just a function with one parameter, and the lambda is just another one. So why does the first work, and not the second? What 'black magic' takes place so that int is not mistaken for a method in the first case?
A python-coded function has a __get__ attribute, a C-function doesn't.
Therefore C1.f performs just the normal attribute lookup while C2.f also
triggers the f.__get__(C2(), C2) call via the descriptor protocol which
happens to return a bound method.
Peter
Le Jeudi 01 Juin 2006 13:34, Peter Otten a écrit*: A python-coded function has a __get__ attribute, a C-function doesn't. Therefore C1.f performs just the normal attribute lookup while C2.f also triggers the f.__get__(C2(), C2) call via the descriptor protocol which happens to return a bound method.
I don't think it's about c-coded versus python-coded stuff, C1.f is a type,
C2.f is a method.
In [14]: class t : pass
....:
In [15]: class u :
....: f = t
....:
....:
In [16]: u().f()
Out[16]: <__main__.t instance at 0xa795a9ec>
--
_____________
Maric Michaud
_____________
Aristote - www.aristote.info
3 place des tapis
69004 Lyon
Tel: +33 426 880 097
Maric Michaud wrote: Le Jeudi 01 Juin 2006 13:34, Peter Otten a écrit*: A python-coded function has a __get__ attribute, a C-function doesn't. Therefore C1.f performs just the normal attribute lookup while C2.f also triggers the f.__get__(C2(), C2) call via the descriptor protocol which happens to return a bound method.
I don't think it's about c-coded versus python-coded stuff, C1.f is a type, C2.f is a method.
You are right, int is a type not a function, but presence (and
implementation, of course) of __get__ is still the distinguishing factor: class Int(int):
.... class __metaclass__(type):
.... def __get__(*args): print "XXX", args
.... class C:
.... int = Int
.... C().int
XXX (<class '__main__.Int'>, <__main__.C instance at 0x402948cc>, <class
__main__.C at 0x40281f2c>)
Also:
from math import sin sin
<built-in function sin> def son(x): pass
.... class C:
.... sin = sin
.... son = son
.... C().sin(0)
0.0 C().son(0)
Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: son() takes exactly 1 argument (2 given)
Peter
On 1/06/2006 9:46 PM, Maric Michaud wrote: Le Jeudi 01 Juin 2006 13:34, Peter Otten a écrit : A python-coded function has a __get__ attribute, a C-function doesn't. Therefore C1.f performs just the normal attribute lookup while C2.f also triggers the f.__get__(C2(), C2) call via the descriptor protocol which happens to return a bound method. I don't think it's about c-coded versus python-coded stuff, C1.f is a type, C2.f is a method.
Try putting f = chr (a C function); it behaves like int, not like a
1-arg Python function. See below.
Cheers,
John
C:\junk>type func_meth.py
class C:
f = None
def __init__(self):
if self.f is not None:
self.x = self.f(0)
else:
self.x = 99 # differs from int(0) :-)
class C1(C):
f = int
class C2(C):
def f(self, arg):
return arg != 0
class C3(C):
pass
class C4(C):
f = chr
for cls in (C1, C2, C3, C4):
o = cls()
print "callable: %r; result: %r" % (o.f, o.x)
C:\junk>func_meth.py
callable: <type 'int'>; result: 0
callable: <bound method C2.f of <__main__.C2 instance at 0x00AE6F58>>;
result: False
callable: None; result: 99
callable: <built-in function chr>; result: '\x00'
C:\junk>
Peter Otten wrote: Eric Brunel wrote:
My actual question is: why does it work in one case and not in the other? As I see it, int is just a function with one parameter, and the lambda is just another one. So why does the first work, and not the second? What 'black magic' takes place so that int is not mistaken for a method in the first case?
A python-coded function has a __get__ attribute, a C-function doesn't. Therefore C1.f performs just the normal attribute lookup while C2.f also triggers the f.__get__(C2(), C2) call via the descriptor protocol which happens to return a bound method.
FWIW:
class Obj(object):
def __new__(cls, val, *args, **kw):
print "in Obj.__new__"
print "- called with :"
print " cls :", cls
print " val :", val
print " args:", str(args)
print " kw :", kw
obj = object.__new__(cls, *args, **kw)
print "got : %s - %s" % (obj, dir(obj))
return obj
class CPlus(C):
f = Obj
Peter
--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
On Thu, 01 Jun 2006 13:34:53 +0200, Peter Otten <__*******@web.de> wrote: Eric Brunel wrote:
My actual question is: why does it work in one case and not in the other? As I see it, int is just a function with one parameter, and the lambda is just another one. So why does the first work, and not the second? What 'black magic' takes place so that int is not mistaken for a method in the first case? A python-coded function has a __get__ attribute, a C-function doesn't. Therefore C1.f performs just the normal attribute lookup while C2.f also triggers the f.__get__(C2(), C2) call via the descriptor protocol which happens to return a bound method.
Thanks for your explanations, Peter. I'll have to find another way to do
what I want...
--
python -c "print ''.join([chr(154 - ord(c)) for c in
'U(17zX(%,5.zmz5(17l8(%,5.Z*(93-965$l7+-'])"
Michael Yanowitz wrote: Hello:
I have a Tkinter GUI Dialog with many buttons and labels and text widgets.
So start a *new* thread.
Le Jeudi 01 Juin 2006 13:12, Eric Brunel a écrit*: Thanks for your explanations, Peter. I'll have to find another way to do * what I want...
maybe :
class C:
* *f = None
* *def __init__(self):
* * *if self.f is not None:
* * * *self.x = self.f(0)
* * *else:
* * * *self.x = 0
class C2(C):
* *def __init__(self) :
self.f = lambda x: x != 0
--
_____________
Maric Michaud
_____________
Aristote - www.aristote.info
3 place des tapis
69004 Lyon
Tel: +33 426 880 097
Eric Brunel wrote: On Thu, 01 Jun 2006 13:34:53 +0200, Peter Otten <__*******@web.de> wrote:
Eric Brunel wrote:
My actual question is: why does it work in one case and not in the other? As I see it, int is just a function with one parameter, and the lambda is just another one. So why does the first work, and not the second? What 'black magic' takes place so that int is not mistaken for a method in the first case? A python-coded function has a __get__ attribute, a C-function doesn't. Therefore C1.f performs just the normal attribute lookup while C2.f also triggers the f.__get__(C2(), C2) call via the descriptor protocol which happens to return a bound method.
Thanks for your explanations, Peter. I'll have to find another way to do what I want...
Maybe just
class C2(C):
f*=*staticmethod(lambda*x:*x*!=*0)
Peter
Eric Brunel wrote: Hi all,
I just stepped on a thing that I can't explain. Here is some code showing the problem:
----------------------------- class C:
Do yourself a favour : use new-style classes.
class C(object)
f = None def __init__(self): if self.f is not None: self.x = self.f(0) else: self.x = 0
class C1(C): f = int
class C2(C): f = lambda x: x != 0
o1 = C1() print o1.x
o2 = C2() print o2.x -----------------------------
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)
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
So the first works and o1.x is actually 0.
int is not a function. type(int)
<type 'type'>
int is a type. A Python type is a callable object, and act as a factory
for instances of it. If the type doesn't implement the descriptor
protocol, when bound to a class and looked up via an instance, normal
lookup rules apply. So the type object is returned as is.
In your case, since int does'nt implement the descriptor protocol, once
looked up (and returned as is), it's called with a correct argument - so
everything runs fine.
Try this:
class Obj(object):
def __new__(cls, val, *args, **kw):
print "in Obj.__new__"
print "- called with :"
print " cls :", cls
print " val :", val
print " args: %s" % str(args)
print " kw : %s" % kw
obj = object.__new__(cls, *args, **kw)
print "got : %s - %s" % (obj, dir(obj))
return obj
def __init__(self, *args, **kw):
print "in Obj.__init__"
print "- called with :"
print " args: %s" % str(args)
print " kw : %s" % kw
class C4(C):
f = Obj
But the second fails because self is also being passed as the first argument to the lambda.
Of course. It's a function, and it's bound to a class, and looked up via
an instance of the class.
Try this:
def truc(*args, **kw):
print "in truc()__"
print "- called with :"
print " args: %s" % str(args)
print " kw : %s" % kw
if len(args) > 1:
return args[1]
class C6(C):
f = truc
Defining a "real" function doesn't help: the error is the same.
What' a "real" function ?-) lambdas *are* real functions. type(lambda x: x)
<type 'function'>
My actual question is: why does it work in one case and not in the other?
cf above.
As I see it, int is just a function with one parameter,
Nope, it's a type. Functions are just one kind of callable. Types are
callables too, as are any object overloading the call operator - which
is '()' - by implementing the __call__(self, ...) method.
class NotAFunc(object):
def __call__(self):
print "I'm not a function"
return 42
func = NotAFunc()
func()
and the lambda is just another one.
True. And functions implement the descriptor protocol.
So why does the first work, and not the second? What 'black magic' takes place so that int is not mistaken for a method in the first case?
cf above.
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
--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
Eric Brunel a écrit : On Thu, 01 Jun 2006 13:34:53 +0200, Peter Otten <__*******@web.de> wrote:
Eric Brunel wrote:
My actual question is: why does it work in one case and not in the other? As I see it, int is just a function with one parameter, and the lambda is just another one. So why does the first work, and not the second? What 'black magic' takes place so that int is not mistaken for a method in the first case?
A python-coded function has a __get__ attribute, a C-function doesn't. Therefore C1.f performs just the normal attribute lookup while C2.f also triggers the f.__get__(C2(), C2) call via the descriptor protocol which happens to return a bound method.
Thanks for your explanations, Peter. I'll have to find another way to do what I want...
You have 2 ways to do it already, here's a third :
class C:
f = None
def __init__(self):
if self.__class__.f is not None:
self.x = self.__class__.f(0)
else:
self.x = 0
Le Jeudi 01 Juin 2006 15:36, Christophe a écrit*: * * * *self.x = self.__class__.f(0)
nope, this will result in a TypeError "unbound method must be called with
instance as first argument"
--
_____________
Maric Michaud
_____________
Aristote - www.aristote.info
3 place des tapis
69004 Lyon
Tel: +33 426 880 097
On Thu, 01 Jun 2006 15:07:26 +0200, bruno at modulix <on***@xiludom.gro>
wrote: Do yourself a favour : use new-style classes. class C(object)
I would if I could: I'm stuck with Python 2.1 for the moment (I should
have mentionned it; sorry for that).
[snip] 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)
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
So the first works and o1.x is actually 0.
int is not a function. type(int) <type 'type'>
int is a type.
Python 2.1 again: type(int)
<type 'builtin_function_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] 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
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.zmz5(17l8(%,5.Z*(93-965$l7+-'])"
Eric Brunel a écrit : On Thu, 01 Jun 2006 15:07:26 +0200, bruno at modulix <on***@xiludom.gro> wrote:
Do yourself a favour : use new-style classes. class C(object)
I would if I could: I'm stuck with Python 2.1 for the moment (I should have mentionned it; sorry for that).
Err, yes - it actually makes most of my explanations inaccurate.
[snip]
(snip too)
Maric Michaud a écrit : Le Jeudi 01 Juin 2006 15:36, Christophe a écrit :
self.x = self.__class__.f(0)
nope, this will result in a TypeError "unbound method must be called with instance as first argument"
Your right :(
staticmethod it is then. This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics
by: R.G. Vervoort |
last post by:
I am using a javafunction (onclick in select) in which i am calling a
function in php (thats why i send this to both php and javascript
newsgroups).
in the onclick i call the function...
|
by: Lenard Lindstrom |
last post by:
I was wondering if anyone has suggested having Python determine
a method's kind from its first parameter. 'self' is a de facto
reserved word; 'cls' is a good indicator of a class method
( __new__...
|
by: Bern McCarty |
last post by:
I have run an experiment to try to learn some things about floating point
performance in managed C++. I am using Visual Studio
2003. I was hoping to get a feel for whether or not it would make...
|
by: Alexis Nikichine |
last post by:
Hello,
Today, I have a function:
function f()
{
}
and am looking for a way of distinguishing, from inside f, whether it
|
by: ragtopcaddy via AccessMonster.com |
last post by:
I have a couple of questions regarding the use of the following function:
Public Function dbLocal(Optional ysnInitialize As Boolean = True) As DAO.
Database
1. Do I just replace all the...
|
by: alexander.stippler |
last post by:
Hi
I wonder if their will be a performance penalty in the following
situation due to virtual function calls:
class Interface
{
public:
virtual void methodA() = 0;
virtual void methodB() =...
|
by: Ravishankar S |
last post by:
Dear C Experts,
While prepating a content for a C course,I made section on function
prototypes.
Could you kindly provide me your comments on its correctness. Thank you !
Q12: What is the...
|
by: Andrew Poulos |
last post by:
Say I have this
foo = function() {
// blah
};
bar = fuction(fnName) {
/* If fnName equalled "foo"
* How do I test that foo, as a function,
* exists and then, if it exists, call it?
|
by: souporpower |
last post by:
Hello All
I am trying to activate a link using Jquery. Here is my code;
<html>
<head>
<script type="text/javascript" src="../../resources/js/
jquery-1.2.6.js"</script>
<script...
|
by: ryjfgjl |
last post by:
ExcelToDatabase: batch import excel into database automatically...
|
by: isladogs |
last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM).
In this month's session, we are pleased to welcome back...
|
by: Vimpel783 |
last post by:
Hello!
Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
|
by: PapaRatzi |
last post by:
Hello,
I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
|
by: CloudSolutions |
last post by:
Introduction:
For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
|
by: Shællîpôpï 09 |
last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
|
by: af34tf |
last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you
|
by: Faith0G |
last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
|
by: isladogs |
last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM).
In this session, we are pleased to welcome former...
| |