473,513 Members | 2,391 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Confused with methods

jfj
I don't understand.
We can take a function and attach it to an object, and then call it
as an instance method as long as it has at least one argument:

#############
class A:
pass

def foo(x):
print x

A.foo = foo
a=A()
a.foo()
#############

However this is not possible for another instance method:

############
class A:
pass

class B:
def foo(x,y)
print x,y

b=B()
A.foo = b.foo
a=A()

# error!!!
a.foo()
##############

Python complains that 'foo() takes exactly 2 arguments (1 given)'.
But by calling "b.foo(1)" we prove that it is indeed a function which takes
exactly one argument.

Isn't that inconsistent?

Thanks,

Gerald.

Jul 18 '05 #1
31 1618

"jfj" <jf*@freemail.gr> wrote in message
news:ma***************************************@pyt hon.org...
I don't understand.
We can take a function and attach it to an object, and then call it
as an instance method as long as it has at least one argument:

#############
class A:
pass

def foo(x):
print x

A.foo = foo
a=A()
a.foo()
#############

However this is not possible for another instance method:

############
class A:
pass

class B:
def foo(x,y)
print x,y

b=B()
A.foo = b.foo
a=A()

# error!!!
a.foo()
##############

Python complains that 'foo() takes exactly 2 arguments (1 given)'.
But by calling "b.foo(1)" we prove that it is indeed a function which
takes
exactly one argument.

Isn't that inconsistent?


You called b.foo(1) but a.foo(). Note one argument in the first call and no
arguments in the second call. Would you have called a.foo(1), you would
have gotten the same result as with b.foo(1). I suppose that was just a
small omission on your part, but what are you trying to do anyway? It's a
very strange use of instance methods.
Jul 18 '05 #2
jfj <jf*@freemail.gr> wrote:
I don't understand.
We can take a function and attach it to an object, and then call it
as an instance method as long as it has at least one argument:

#############
class A:
pass

def foo(x):
print x

A.foo = foo
a=A()
a.foo()
#############
Right. If you want to understand how this happens, look at the
foo.__get__ special method, which makes foo (like every other function)
a *descriptor*. One you've set foo as an attribute of class A, the
access a.foo calls foo.__get__(a, A) which returns an object of class
"instance method".

However this is not possible for another instance method:

############
class A:
pass

class B:
def foo(x,y)
print x,y

b=B()
A.foo = b.foo
What you're assigning here as an attribute of class A is not a
descriptor: it does not have a special method __get__.
a=A()

# error!!!
a.foo()
Since A.foo does not have a method __get__, it's just returned when you
access it (on instance a). It's already an instance method -- but it's
bound to instance b of class B.
##############

Python complains that 'foo() takes exactly 2 arguments (1 given)'.
But by calling "b.foo(1)" we prove that it is indeed a function which takes
exactly one argument.
Calling something does not prove it's a function. Python has a lot of
callable objects, and functions are just one callable types. So, you're
mistaken if you think that by calling (whatever) you prove said whatever
is a function (of any kind).

The error message you're seeing does come from a function -- the im_func
attribute of b.foo, which is a function foo taking two arguments
(created and set into class B by the "def foo(x, y):" above, even though
you forgot the colon I'm sure you intended to type it).

Isn't that inconsistent?


That Python has many callable types, not all of which are descriptors?
I don't see any inconsistency there. Sure, a more generalized currying
(argument-prebinding) capability would be more powerful, but not more
consistent (there's a PEP about that, I believe).

If what you want is to focus on the error message, you can completely
separate it from the idea of having set b.foo as an attribute of class
A. Just try calling b.foo() without arguments and you'll get exactly
the same error message -- from the underlying function foo, which is
also b.foo.im_func (the function's FIRST argument is bound to
b.foo.im_self, which is b; whence the error being about function foo
taking exactly two arguments and only one having been given).
Alex
Jul 18 '05 #3
jfj
Dan Perl wrote:
"jfj" <jf*@freemail.gr> wrote in message
news:ma***************************************@pyt hon.org...

However this is not possible for another instance method:

############
class A:
pass

class B:
def foo(x,y)
print x,y

b=B()
A.foo = b.foo
a=A()

# error!!!
a.foo()
##############

Python complains that 'foo() takes exactly 2 arguments (1 given)'.
But by calling "b.foo(1)" we prove that it is indeed a function which
takes
exactly one argument.

Isn't that inconsistent?

You called b.foo(1) but a.foo(). Note one argument in the first call and no
arguments in the second call. Would you have called a.foo(1), you would
have gotten the same result as with b.foo(1). I suppose that was just a
small omission on your part, but what are you trying to do anyway? It's a
very strange use of instance methods.


No omission.
If I say:

x=b.foo
x(1)

Then, without looking at the previous code, one can say that "x" is a
function which takes one argument. Continuing with "x":

A.foo = x
# this is ok
A.foo(1)
a=A()
# this is not ok
a.foo()

I expected that when we add this "x" to a class's dictionary and
then we request it from an instance of that class, it will be
converted to an bound-method and receive its --one-- argument
from the referring instance.

So "a.foo()" == "A.foo(a)" == "x(a)" == "b.foo(a)" == "B.foo(b,a)",
or at least "why not?" (head exploded?:)

I'm not trying to do something specific with this though.
G.
Jul 18 '05 #4
jfj
Alex Martelli wrote:
jfj <jf*@freemail.gr> wrote:
Isn't that inconsistent?

That Python has many callable types, not all of which are descriptors?
I don't see any inconsistency there. Sure, a more generalized currying
(argument-prebinding) capability would be more powerful, but not more
consistent (there's a PEP about that, I believe).


Thanks for the explanation.

The inconsistency I see is that if I wanted this kind of behavior
I would've used the staticmethod() builtin (which in a few words
alters __get__ to return the function unmodified).

So I would write

A.foo = staticmethod (b.foo)

But now, it always acts as staticmethod:(

Anyway, if there's a PEP about it, I'm +1 because its "pythonic".
G.

Jul 18 '05 #5
> I expected that when we add this "x" to a class's dictionary and
then we request it from an instance of that class, it will be
converted to an bound-method and receive its --one-- argument
from the referring instance.


Here you are wrong: your b.foo is a bound method - it already _has_ its
first argument (an instance of B) bound to it. And just passing it around
doesn't change that. You can assign it to a name in whatever scope you like
- that won't change its nature.

Now if you want to use foo in A as instancemethod, you could do this:

A.foo = b.foo.im_func
a = A()
a.foo(200)
That works because im_func is a "pure" function:
B.foo.im_func

<function foo at 0xb7ac47d4>
If things worked as you wanted it to, that would mean that passing a bound
method as argument to a class and storing it there to a instance variable
that would "eat up" the arguments - surely not the desired behaviour.
--
Regards,

Diez B. Roggisch
Jul 18 '05 #6
jfj <jf*@freemail.gr> wrote:
If I say:

x=b.foo
x(1)

Then, without looking at the previous code, one can say that "x" is a
function which takes one argument.


One can say whatever one wishes, but saying it does not make it true.

One can say that x is a green frog, but that's false: x is a
boundmethod.

One can say that x is a function, but that's false: x is a boundmethod.

One can say that x is a spade, but that's false: x is a boundmethod.
You can call green frogs (with a suitable whistling), you can call
functions, and you can call a spade (a spade). The fact that they're
all callable (since you can call them), and a boundmethod is also
callable, does not necessarily make them equivalent to each other, nor
any of them equivalent to a boundmethod, in any other way whatsoever.
Alex
Jul 18 '05 #7
jfj <jf*@freemail.gr> wrote:
Isn't that inconsistent?


That Python has many callable types, not all of which are descriptors?
I don't see any inconsistency there. Sure, a more generalized currying
(argument-prebinding) capability would be more powerful, but not more
consistent (there's a PEP about that, I believe).


Thanks for the explanation.

The inconsistency I see is that if I wanted this kind of behavior
I would've used the staticmethod() builtin (which in a few words
alters __get__ to return the function unmodified).


The staticmethod builtin would NOT have given you the behavior: "bind
the first argument". I do not know what you mean by "this kind of
behavior", but making a boundmethod most assuredly DOES give you
extremely different behavior from wrapping a function in staticmethod.

I still wouldn't see any "inconsistency" even if two different ways of
proceeding gave the same result in a certain case. That would be like
saying that having x-(-y) give the same result as x+y (when x and y are
numbers) is ``inconsistent''... the word ``inconsistent'' just doesn't
MEAN that!

"Inconsistent" means sort of the reverse: one way of proceeding giving
different results. But the fact that the same operation on objects of
different types may well give different results isn't _inconsistent_ --
it's the sole purpose of HAVING different types in the first place...!
Alex
Jul 18 '05 #8
jfj
Alex Martelli wrote:

I still wouldn't see any "inconsistency" even if two different ways of
proceeding gave the same result in a certain case. That would be like
saying that having x-(-y) give the same result as x+y (when x and y are
numbers) is ``inconsistent''... the word ``inconsistent'' just doesn't
MEAN that!

"Inconsistent" means sort of the reverse: one way of proceeding giving
different results. But the fact that the same operation on objects of
different types may well give different results isn't _inconsistent_ --
it's the sole purpose of HAVING different types in the first place...!


Ok! I said I was confused in the first place!
G.

Jul 18 '05 #9
jfj
Alex Martelli wrote:
jfj <jf*@freemail.gr> wrote:
Then, without looking at the previous code, one can say that "x" is a
function which takes one argument.

One can say whatever one wishes, but saying it does not make it true.

One can say that x is a green frog, but that's false: x is a
boundmethod.

One can say that x is a function, but that's false: x is a boundmethod.

One can say that x is a spade, but that's false: x is a boundmethod.


I understand that a function and a boundmethod are *different* things.
For one a *boundmethod* has the attributes im_self, im_class, which
a function does not have (a green frog neither). Thus they are not
the same thing.

HOWEVER, what I ask is WHY don't we set the tp_descr_get of
the boundmethod object to be the same as the func_descr_get???
Or WHY do they *have* to differ in this specific part?

I quickly looked at the source of python and it seems that a
one-liner would be enough to enable this. So it's not that it
would be hard to implement it, or inefficient.

A bound method would *still* be a boundmethod.
We could additionally have:
type(x)

<boundmethod of <boundmethod of <boundmethod of....<__main__.A
instance at 0x>>>

If there a good reason that the __get__ of a boundmethod does not
create a new boundmethod wrapper over the first boundmethod?
G.
Jul 18 '05 #10

On 2005 Feb 07, at 22:15, jfj wrote:
Alex Martelli wrote:
jfj <jf*@freemail.gr> wrote:
Then, without looking at the previous code, one can say that "x" is a
function which takes one argument. One can say whatever one wishes, but saying it does not make it true.
One can say that x is a green frog, but that's false: x is a
boundmethod.
One can say that x is a function, but that's false: x is a
boundmethod.
One can say that x is a spade, but that's false: x is a boundmethod.


I understand that a function and a boundmethod are *different* things.
For one a *boundmethod* has the attributes im_self, im_class, which
a function does not have (a green frog neither). Thus they are not
the same thing.


Great! So, do *NOT* ``say that "x" is a function'', when you know that
is false.
HOWEVER, what I ask is WHY don't we set the tp_descr_get of
the boundmethod object to be the same as the func_descr_get???
Or WHY do they *have* to differ in this specific part?
Why we don't change boundmethods' binding behavior NOW is obvious --
can't break backwards compatibility. If you're talking about Python
3.0, which _will_ be allowed to break backwards compatibility when it
comes, then I, personally, have no special objection to changing that
binding behavior; a PEP may be necessary, of course, but it may also be
possible to get the idea into the existing PEP 3000 by presenting a
good case on python-dev (not here -- no decisions on Python's future
are made here).
I quickly looked at the source of python and it seems that a
one-liner would be enough to enable this. So it's not that it
You looked too quickly. Currently, PyMethod objects are used to
implement both bound and unbound methods, and function
instancemethod_descr_get (around line 2430 of classobject.c) has the
logic to implement the differences in __get__ behavior between them.
Recently GvR mused about doing away with unbound-methods per se, but
after some discussion on python-dev he currently seems to have
withdrawn the proposal; you may want to read that discussion in the
python-dev archives since it's relevant to prototyping your idea. In
any case, a one-liner would not be enough, although:
would be hard to implement it, or inefficient.
....that doesn't necessarily make it either hard or inefficient.
If there a good reason that the __get__ of a boundmethod does not
create a new boundmethod wrapper over the first boundmethod?


There might be some inefficiencies in the multiple indirections, but
that remains to be proven until we have a prototype. Besides, if there
are, the right approach would probably be to have some generalization
of boundmethods able to bind the first N arguments rather than one at a
time.
Alex

Jul 18 '05 #11
> HOWEVER, what I ask is WHY don't we set the tp_descr_get of
the boundmethod object to be the same as the func_descr_get???
Or WHY do they *have* to differ in this specific part?

I quickly looked at the source of python and it seems that a
one-liner would be enough to enable this. So it's not that it
would be hard to implement it, or inefficient.

A bound method would *still* be a boundmethod.
We could additionally have:
>>>type(x)

<boundmethod of <boundmethod of <boundmethod of....<__main__.A
instance at 0x>>>

If there a good reason that the __get__ of a boundmethod does not
create a new boundmethod wrapper over the first boundmethod?


I already gave you the good reason:

class A:
def callback(self, arg):
print self, arg

def callback(arg):
print arg

class DoSomethingWithCallback:
def __init__(self, cb):
self.cb = cb

def run(self):
for i in xrange(100):
self.cb(i)

u = DoSomethingWithCallback(A().callback)
v = DoSomethingWithCallback(callback)

# would crash if your suggestion worked
u.run()
v.run()
Bound methods aren't a general purpose currying scheme - they exist sorely
for the OO-style implicit first argument. That they exist at all is a great
difference to e.g. C++, where you can't pass callbacks around that are
instance methods.

If you are after currying - look at the cookbook, there are recipes for
that.
--
Regards,

Diez B. Roggisch
Jul 18 '05 #12
Op 2005-02-06, Alex Martelli schreef <al*****@yahoo.com>:
Isn't that inconsistent?


That Python has many callable types, not all of which are descriptors?
I don't see any inconsistency there. Sure, a more generalized currying
(argument-prebinding) capability would be more powerful, but not more
consistent (there's a PEP about that, I believe).


I think python is a bit inconsistent here, by using 'def' for
two different things. I think it would have been more consistent
if def always produces a function to be used as such and that
methods had there own keyword. That would make the magic of
bound methods more explicit.

--
Antoon Pardon
Jul 18 '05 #13
jfj

Hello Diez.
I sent a reply to the previous message requesting an example of
what would break, but unfortunatelly it didn't make it in python-list.
Here it is for the record [
Diez B. Roggisch wrote:
If things worked as you wanted it to, that would mean that passing bound
method as argument to a class and storing it there to an instance variable
that would "eat up" the arguments - surely not the desired behaviour.

Could you please give an example of this ?

If you mean:

class A:
def f(x):
print x

class B:
pass

a=A()
B.f = a.f
b=B()
b.f() #surprise: it works!!

then that is equally "weird" as my case. "eat up" sounds
rather bad but all what will happen is an argument number
mismatch.
In fact is seems more appropriate to use a.f.im_func in this
case to "convert the bound method to an unbound one".

Maybe this happens more often?
Thanks,

G.

]

Diez B. Roggisch wrote:
If there a good reason that the __get__ of a boundmethod does not
create a new boundmethod wrapper over the first boundmethod?

I already gave you the good reason:

class A:
def callback(self, arg):
print self, arg

def callback(arg):
print arg

class DoSomethingWithCallback:
def __init__(self, cb):
self.cb = cb

def run(self):
for i in xrange(100):
self.cb(i)

u = DoSomethingWithCallback(A().callback)

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Oops!!!
I think it would be more obvious to somebody who doesn't know
the python internals, to say:
# take the callback from A and install it to DSWC
u=DoSomethingWithCallback( A.callback)
or
u=DoSomethingWithCallback (A().callback.im_func)
or
u=DoSomethingWithCallback (A().im_class.callback)

v = DoSomethingWithCallback(callback)

# would crash if your suggestion worked
u.run()
v.run()

It would complain about not enough arguments.
As it does in the case I'm confused about!
If you are after currying - look at the cookbook, there are recipes for
that.


I'm satistfied with Alex's response that it is like that for backwards
compatibility, but in Python 3000 it may be the other way around.
Thanks all.

jfj

Jul 18 '05 #14
Antoon Pardon <ap*****@forel.vub.ac.be> wrote:
Op 2005-02-06, Alex Martelli schreef <al*****@yahoo.com>:
Isn't that inconsistent?
That Python has many callable types, not all of which are descriptors?
I don't see any inconsistency there. Sure, a more generalized currying
(argument-prebinding) capability would be more powerful, but not more
consistent (there's a PEP about that, I believe).


I think python is a bit inconsistent here, by using 'def' for
two different things.


It doesn't.
I think it would have been more consistent
if def always produces a function


It does.

def g(self): pass
class A(object):
f = g

class B(object):
def f(self): pass

class C(object): pass
C.f = g

class D(object):
f = B.f

These four classes are essentially equivalent. def always produces a
function object and binds it to the name coming after keyword 'def'.
Any such function object, no matter how produced and how bound hither
and thither, always behaves in exactly the same way.

You're free to like or dislike this arrangement, but calling it
"inconsistent" is a madman's folly, as it is TOTALLY consistent.
Alex

Jul 18 '05 #15
Diez B. Roggisch <de*********@web.de> wrote:
...
If there a good reason that the __get__ of a boundmethod does not
create a new boundmethod wrapper over the first boundmethod?
I already gave you the good reason:


Hmmm, not sure the code below is ``a good reason'' to avoid changing the
__get__ behavior of boundmethods come Python 3.0 time. Assume all
classes are newstyle (they'll be, in 3.0), not that it matters here (I
think):
class A:
def callback(self, arg):
print self, arg

def callback(arg):
print arg

class DoSomethingWithCallback:
def __init__(self, cb):
self.cb = cb
Here we're setting an INSTANCE attribute,
def run(self):
for i in xrange(100):
self.cb(i)
....and here we're fetching it back. So, it doesn't matter if the cb
argument is a descriptor of whatever variant -- it must be callable, and
that's all we ask of it. IOW, cb.__get__ -- whether it exists at all,
and what it does -- just doesn't *matter*; cb.__call__ is all that does
matter.
u = DoSomethingWithCallback(A().callback)
v = DoSomethingWithCallback(callback)

# would crash if your suggestion worked
u.run()
v.run()
I don't think there would be any crash, because the idea is about
changing some __get__ behavior, NOT any __call__ behavior, and no
__get__ is involved in this example.

If strong use cases exist for a boundmethod's __get__ keeping its
current behavior (apart from the obvious backwards compatibility issues
which mean that any change will have to wait for 3.0), I don't think
this can be one.

Bound methods aren't a general purpose currying scheme - they exist sorely
for the OO-style implicit first argument. That they exist at all is a great
difference to e.g. C++, where you can't pass callbacks around that are
instance methods.
This is historically true. However, this historical fact is not
necessarily a reason for keeping the current lower-power behavior of
boundmethods, when 3.0 allows breaking backwards compatibility.

If you are after currying - look at the cookbook, there are recipes for
that.


Sure, I wrote some of them;-). But since we're talking about future
prospects, I think the PEP on partial application is more relevant than
the current pure-Python workarounds. They _are_ workarounds, btw --
partial application, aka currying, is an important general idea; it can
be implemented in Python, but it's not directly part of it. The PEP's
idea is to have that concept directly implemented.

Actually, I believe that if you call new.instancemethod you CAN already
get that effect -- let's see...:
import new
curry = new.instancemethod
def f(a, b, c): print a, b, c .... x = curry(curry(f, 23, object), 45, object)
x(67) 23 45 67

Yep -- just fine (in __call__ terms). Not so in __get__ terms:
class X(object): pass .... X.zap = x
y = X()
y.zap() Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: f() takes exactly 3 arguments (2 given)
So, for generic currying (in the original sense: prebinding the FIRST
argument of any callable), new.instancemethod is OK (even though you
have to pass a third argument of 'object', no big deal), and you can
call it repeatedly. We're only missing a descriptor with a __get__ that
does this appropriately when you set such a ``curried'' callable as a
class attribute.

I'm not sure if the best approach is to change boundmethods' own
__get__, or to have another descriptor for the purpose:
class binder(object): .... def __init__(self, callable): self.callable = callable
.... def __get__(self, obj, cls): return curry(self.callable, obj, cls)
.... X.zap = binder(x)
y.zap() 23 45 <__main__.X object at 0x402dfa8c>

This ``binder'' approach would have the advantage of allowing ANY
callable whatsoever, e.g.:
X.__divmod__ = lambda self, other: (self, other)
divmod(y, 23) (<__main__.X object at 0x402dfa8c>, 23) X.dm = binder(divmod)
y.dm(23) (<__main__.X object at 0x402dfa8c>, 23)


Of course, a custom metaclass could easily wrap 'binder' around any
class attributes which are callable but aren't descriptors, to get the
same effect more transparently. Hmmmm -- the tradeoffs aren't clear to
me at this time. That's exactly what the PEP process is for... ensure
that any tradeoffs ARE discussed in depth before any change is made.
Alex
Jul 18 '05 #16
On Mon, Feb 07, 2005 at 03:24:11PM +0100, Alex Martelli wrote:
def always produces a
function object and binds it to the name coming after keyword 'def'.
Any such function object, no matter how produced and how bound hither
and thither, always behaves in exactly the same way.


This isn't exactly true:
class C(object): ... def __new__(*a): pass
... C.__new__ <function __new__ at 0x40088d4c> class D(object): pass ... def __new__(*a): pass ... D.__new__ = __new__
D.__new__

<unbound method D.__new__>

of course, __new__ is special-cased (*some*body should've read "import
this", especially the part "explicit is better than implicit").

--
John Lenton (jo**@grulic.org.ar) -- Random fortune:
Al freír será el reír.

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.5 (GNU/Linux)

iD8DBQFCB3//gPqu395ykGsRAj+oAKCTuBPtru/i2eRKGmglq9V3xD7ePACeNPBB
a1jyxnxo1mQp9372+wimRnQ=
=bDQb
-----END PGP SIGNATURE-----

Jul 18 '05 #17
Op 2005-02-07, Alex Martelli schreef <al*****@yahoo.com>:
Antoon Pardon <ap*****@forel.vub.ac.be> wrote:
Op 2005-02-06, Alex Martelli schreef <al*****@yahoo.com>:
>
>> Isn't that inconsistent?
>
> That Python has many callable types, not all of which are descriptors?
> I don't see any inconsistency there. Sure, a more generalized currying
> (argument-prebinding) capability would be more powerful, but not more
> consistent (there's a PEP about that, I believe).


I think python is a bit inconsistent here, by using 'def' for
two different things.


It doesn't.
I think it would have been more consistent
if def always produces a function


It does.

def g(self): pass
class A(object):
f = g

class B(object):
def f(self): pass

class C(object): pass
C.f = g

class D(object):
f = B.f

These four classes are essentially equivalent. def always produces a
function object and binds it to the name coming after keyword 'def'.
Any such function object, no matter how produced and how bound hither
and thither, always behaves in exactly the same way.

You're free to like or dislike this arrangement, but calling it
"inconsistent" is a madman's folly, as it is TOTALLY consistent.


Yes it is inconsistent with the rest of python. That you found
a subset in which it is consistent doesn't change that.

And what if you do:

c = C()
c.f = g
The fact that a function in a class performs a lot of magic if
it is called through an instance, that isn't performed otherwise,
makes python inconsistent here. You may like the arrangement
(and it isn't such a big deal IMO) but that doesn't make it consistent.

--
Antoon Pardon
Jul 18 '05 #18
On Mon, Feb 07, 2005 at 02:53:49PM +0000, Antoon Pardon wrote:
The fact that a function in a class performs a lot of magic if
it is called through an instance, that isn't performed otherwise,
makes python inconsistent here. You may like the arrangement
(and it isn't such a big deal IMO) but that doesn't make it consistent.


I vote for accepting the fact (it goes with the "practicality beats
purity" bit, because otherwise all our methods would have to start
with an @instancemethod). This doesn't justify (IMVVHO) a new keyword,
like you (was it you?) seemed to imply (do you really mean for
instancemethod (or somesuch) and classmethod to become keywords?). I
think it's fine the way it is: there's an implicit @instancemethod,
and @staticmethod (which you'd have be the default if I read you
right) has to be explicit, when in classes. I think __new__ being an
exception to this is a (minor) wart, in fact it feels like premature
optimization (how many __new__s do you write, that you can't stick a
@staticmethod in front of them?

--
John Lenton (jo**@grulic.org.ar) -- Random fortune:
Fun Facts, #14:
In table tennis, whoever gets 21 points first wins. That's how
it once was in baseball -- whoever got 21 runs first won.

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.5 (GNU/Linux)

iD8DBQFCB4gKgPqu395ykGsRAnfEAJ9Dzqh/5WxP3W2C6EZKdEJ3Dk9CogCeOrDz
Se4r4OBFagG6F6tbnxOUhA0=
=feKR
-----END PGP SIGNATURE-----

Jul 18 '05 #19
Op 2005-02-07, John Lenton schreef <jo**@grulic.org.ar>:


--cvVnyQ+4j833TQvp
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

On Mon, Feb 07, 2005 at 02:53:49PM +0000, Antoon Pardon wrote:
The fact that a function in a class performs a lot of magic if
it is called through an instance, that isn't performed otherwise,
makes python inconsistent here. You may like the arrangement
(and it isn't such a big deal IMO) but that doesn't make it consistent.
I vote for accepting the fact (it goes with the "practicality beats
purity" bit,


But before one can produce the "practicality beats purity" argument,
one has to accept this isn't pure. That was all I was saying here,
python is not consistent/pure here. Now there can be good arguments
to have this that offset the inconsistency, but the python people
shouldn't then try to argue that it is consistent anyway.
because otherwise all our methods would have to start
with an @instancemethod). This doesn't justify (IMVVHO) a new keyword,
like you (was it you?) seemed to imply (do you really mean for
instancemethod (or somesuch) and classmethod to become keywords?). I
think it's fine the way it is: there's an implicit @instancemethod,
and @staticmethod (which you'd have be the default if I read you
right) has to be explicit, when in classes.


I'm not saying I would have it so, I'm saying that would be the
pure/consistent way to do it.

--
Antoon Pardon
Jul 18 '05 #20
Antoon Pardon <ap*****@forel.vub.ac.be> wrote:
Yes it is inconsistent with the rest of python. That you found
a subset in which it is consistent doesn't change that.

And what if you do:

c = C()
c.f = g
The fact that a function in a class performs a lot of magic if
it is called through an instance, that isn't performed otherwise,
makes python inconsistent here. You may like the arrangement
(and it isn't such a big deal IMO) but that doesn't make it consistent.


Any descriptor (be it a function or otherwise) has its __get__ method
called, when _accessed_ by attribute syntax, if and only if that
descriptor is in a class. _ALL_ of Python is perfectly consistent on
this point, and if I didn't already know the kind of crazy and obviously
false assertions that you post *QUITE* consistently, I would be
astonished to see you claim otherwise. Knowing your posts, this latest
idiocy is perfectly "par for the course".

"A lot of magic" is simply a stupid and imprecise way to describe "the
__get__ method gets called". Saying that any of this happens when the
function is CALLED is a definitely more serious mistake, since it's
absolutely obvious that the __get__ method is called when the function
(or any other attribute) is *ACCESSED* -- the call operation (on
whatever object __get__ returns) happens AFTERWARDS.

Why you, and a few other habitual trolls, keep lowering the signal to
noise ratio of this newsgroup with your blatherings, I don't know; I'm
sure this behavior must be giving you guys some kind of satisfaction.
Whether the damage you do to the clarity of the issues, and to the
understanding of newbies who are unfortunate enough to read and trust
the many imprecise and/or utterly false assertions you keep making, with
totally unjustified airs of competence, is part of your jollies, or just
a side effect you don't care a whit about, I don't know either. Guess
I'll just killfile you for another month now -- wish MacSOUP had a
simple way to to permanent killfiling, since it's pretty obvious by now
that it's quite unlikely you'll even post anything worthwhile at all.
Alex
Jul 18 '05 #21
John Lenton <jo**@grulic.org.ar> wrote:
I think __new__ being an
exception to this is a (minor) wart, in fact it feels like premature
optimization (how many __new__s do you write, that you can't stick a
@staticmethod in front of them?


I personally think it's quite reasonable for Python's infrastructure to
consider each special name specially -- that's what the double
underscores before and after are FOR, after all. Since __new__ MUST be
a staticmethod, and there's no use case for it ever being otherwise, it
seems quite sensible for the default metaclass to MAKE it a staticmethod
(and otherwise treat it specially, as it needs to be). I don't see what
optimization has to do with it (quite apart from the fact that __new__
was introduced before the splatsyntax for decorators, so that rather
than sticking anything in front the alternative would have been to
demand serious boilerplate, a '__new__ = staticmethod(__new__)' after
every definition of such a method). Reducing boilerplate with no ill
effects whatsoever seems quite a worthy goal to me, when reachable.
Alex
Jul 18 '05 #22
jfj
Alex Martelli wrote:


I think the problem is that you know python so well that you are used
to the way things are and everything seems natural the way it is.
For a newbie, the behaviour I mentioned seems indeed a bit inconsistent.
"Inconsistent" not as in mathematics but as in "wow! I'd thought this
should work like this". Like you have a perception of the language
and then this feature changes everything. It's a different kind of
"inconsistency" and it doesn't give python a bad name or something,
nor does it break the mathematical laws of the universe.

There is no trolling involved here. Maybe wrong use of the english
language. But then again, this is the newgroups and the english
language is ill-used all the time:)
Regards,

jfj

Jul 18 '05 #23
jfj wrote:
I think the problem is that you know python so well that you are used
to the way things are and everything seems natural the way it is.
For a newbie, the behaviour I mentioned seems indeed a bit inconsistent.
"Inconsistent" not as in mathematics but as in "wow! I'd thought this
should work like this". Like you have a perception of the language
and then this feature changes everything. It's a different kind of
"inconsistency" and it doesn't give python a bad name or something,
nor does it break the mathematical laws of the universe.


Yup, this kind of discovery happens all the time. When you ask about it
though, you should try to be clear that you're asking a question, not
making an assertion. Your post said things like:

....this is not possible...
....we prove that it is indeed a function...
....Isn't that inconsistent?...

This makes you sound very certain of yourself. If you're willing to
acknowledge that your understanding of Python is incomplete and ask
questions instead of making assertions, you'll get a lot fewer hostile
responses to your posts.

For your benefit, and the benefit of others who make this same mistake,
I'll rewrite your original post in a manner that won't seem so
self-important and confrontational[1].

Here's your original post:

----------------------------------------------------------------------
I don't understand.
We can take a function and attach it to an object, and then call it
as an instance method as long as it has at least one argument:

[snip example assigning function to class]

However this is not possible for another instance method:

[snip example assigning instancemethod to class]

Python complains that 'foo() takes exactly 2 arguments (1 given)'.
But by calling "b.foo(1)" we prove that it is indeed a function which takes
exactly one argument.

Isn't that inconsistent?
----------------------------------------------------------------------

And here it is rewritten to sound less confrontational:

----------------------------------------------------------------------
I don't understand.
I can take a function and attach it to an object, and then call it
as an instance method as long as it has at least one argument:

[snip example assigning function to class]

But I don't know how to do the same thing when I get the function from
an instance:

[snip example assigning instancemethod to class]

Python complains that 'foo() takes exactly 2 arguments (1 given)'.

Can someone explain this behavior to me? How would I get a function
from an instance and assign it to a class?
----------------------------------------------------------------------

I've left most of the terminological errors in the question since they
were probably inevitably part of the question. Note however, that my
rewrite of your post makes it clear that you are asking questions, not
making assertions. If you don't make assertions about things you don't
fully understand, you'll have a much easier time on this newsgroup.

Steve

[1] This was probably not the intended air, but that's how it came across.
Jul 18 '05 #24
"jfj" <jf*@freemail.gr> wrote:
u = DoSomethingWithCallback(A().callback) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Oops!!!
I think it would be more obvious to somebody who doesn't know
the python internals, to say:
# take the callback from A and install it to DSWC
u=DoSomethingWithCallback( A.callback)


that's not the same thing.
u=DoSomethingWithCallback (A().callback.im_func)
that's not the same thing.
u=DoSomethingWithCallback (A().im_class.callback)


that's not the same thing.

if you cannot tell the difference between a class and an instance, you should
spend more time learning how Python works, and less time telling everyone
how things can be made more "obvious".

</F>

Jul 18 '05 #25
jfj
Steven Bethard wrote:

For your benefit, and the benefit of others who make this same mistake,
I'll rewrite your original post in a manner that won't seem so
self-important and confrontational[1].


``People who code too much tend to get authoritative'', in general.

I am an arrogant noob -- just like arrogant experts...
Inconsistenly y'rs

jfj

Jul 18 '05 #26
jfj

I just realized that I'm trolling.

We all sometimes get into a trollwar despite our intensions
(even FL). So, I would like to apologize on behalf
of all those who participated in it. I'm sorry you had to witness
that.
jfj

Jul 18 '05 #27
Op 2005-02-07, Alex Martelli schreef <al*****@yahoo.com>:
Antoon Pardon <ap*****@forel.vub.ac.be> wrote:
Yes it is inconsistent with the rest of python. That you found
a subset in which it is consistent doesn't change that.

And what if you do:

c = C()
c.f = g
The fact that a function in a class performs a lot of magic if
it is called through an instance, that isn't performed otherwise,
makes python inconsistent here. You may like the arrangement
(and it isn't such a big deal IMO) but that doesn't make it consistent.
Any descriptor (be it a function or otherwise) has its __get__ method
called, when _accessed_ by attribute syntax, if and only if that
descriptor is in a class. _ALL_ of Python is perfectly consistent on
this point, and if I didn't already know the kind of crazy and obviously
false assertions that you post *QUITE* consistently, I would be
astonished to see you claim otherwise. Knowing your posts, this latest
idiocy is perfectly "par for the course".


No python is not consistent and your continuous repetion doesn't
make it so. To illustrate, here the following code:

class A:
l = []
def f(): pass

a = A()
print a.l is A.l
print a.f is A.f

which produces:

True
False


"A lot of magic" is simply a stupid and imprecise way to describe "the
__get__ method gets called".
So what? That is an implementation detail.
Saying that any of this happens when the
function is CALLED is a definitely more serious mistake, since it's
absolutely obvious that the __get__ method is called when the function
(or any other attribute) is *ACCESSED* -- the call operation (on
whatever object __get__ returns) happens AFTERWARDS.
Fine, I was imprecise. But your harping on my impression doesn't
change the fact that python doesn't work consistent here.
Why you, and a few other habitual trolls, keep lowering the signal to
noise ratio of this newsgroup with your blatherings, I don't know;
Well you can think me a troll, I think you are a zealot who gets
overly defensive if the "wrong" people try to suggest python has
some failing.
I'm
sure this behavior must be giving you guys some kind of satisfaction.
Whether the damage you do to the clarity of the issues, and to the
understanding of newbies who are unfortunate enough to read and trust
the many imprecise and/or utterly false assertions you keep making,
Look we are all people, we all are imprecise at moments, including you.
But when the "wrong" people get imprecise you get into a fit on how
these people are trolls and try to get python into a bad daylight
instead of trying to understand what they really are trying to say
and reacting to that and maybe in the mean time correcting the
imprecession.

In this case the way python accesses class functions from an instance
is not consistent with how python accesses other class attributes
from an instance. I know it is designed that way and I can understand
hwy it was done. But this inconsistency can be a stumbling block for
a newcomer and I think that explaining why the inconsistency is present
is a better option than declaring there is no inconsistency.
with
totally unjustified airs of competence, is part of your jollies, or just
a side effect you don't care a whit about, I don't know either. Guess
I'll just killfile you for another month now -- wish MacSOUP had a
simple way to to permanent killfiling, since it's pretty obvious by now
that it's quite unlikely you'll even post anything worthwhile at all.


Well whether I post something that is worthwhile to you, can only be
decided by you. I sometimes have my doubts about you too.

--
Antoon Pardon
Jul 18 '05 #28
jfj <jf*@freemail.gr> wrote:
I just realized that I'm trolling.


I'm glad you're retracting your earlier assertion that "There is no
trolling involved here". Everybody can err, but to admit and apologize
takes character: may I offer my warmest handshake.

Back when I was a Python newbie (and identified as such even in the
Subject of my early posts) I had my ideas about how Python should
change, too: it should grow a '__contains__' special method to let a
container optimize membership tests (the `in' operator); it should have
a specialized iterator protocol, rather than always relying on indexing
for iteration; it should be possible to subclass builtin types, e.g.
dictionary; ... you can read all about it on google, including my
request to """Please consider "IMHO"'s to be liberally inserted in what
follows, of course!-)."""

It turned out that __contains__ was already in the plans (which I did
not know about): I had even guessed the *name*! The iterator protocol
and subclassing builtin types took a bit longer to appear (and the
eventual name was __iter__ while my original idea was __enum__; and it's
still not fully possible insert a subclassed dict anywhere a dict may be
used) but eventually they did.

And yet for all of this I ended up in a flamewar with the timbot
anyway... it solved itself and we made friends, but still, I'm quite
familiar with the pickles a newbie can get into;-).
Alex
Jul 18 '05 #29
> No python is not consistent and your continuous repetion doesn't
make it so. To illustrate, here the following code:

class A:
l = []
def f(): pass

a = A()
print a.l is A.l
print a.f is A.f

which produces:

True
False


Thats only inconsistent from your POV because you refuse to accept that the
scope of a function definition does matter. And as usual its a topic of
totally unrelevant practical impact and an expression of your strangely
deeprooted desire to nitpick at such unrelevant details.

Why don't you pick something that really bothers people and see if your
skills (that I'm sure exist) can be of use there?

--

Regards,

Diez B. Roggisch
Jul 18 '05 #30
Op 2005-02-08, Diez B. Roggisch schreef <de*********@web.de>:
No python is not consistent and your continuous repetion doesn't
make it so. To illustrate, here the following code:

class A:
l = []
def f(): pass

a = A()
print a.l is A.l
print a.f is A.f

which produces:

True
False
Thats only inconsistent from your POV because you refuse to accept that the
scope of a function definition does matter.


It doesn't. As Alex has already explained, the above is equivallent to:

def h(): pass

class A:
l = []
f = h

a = A()
print a.l is A.l
print a.f is A.f
And such great error would surely brand you a Troll in his eyes.
Scope of definition has nothing to do with it. The only factor
that matters in this case is if the function is a class atribute
or not.
And as usual its a topic of
totally unrelevant practical impact and an expression of your strangely
deeprooted desire to nitpick at such unrelevant details.
If I told you that this detail, well not this particular one but
one that is close to it, will break one of my applications in
the transition from python 2.3 to 2.4, do you still think
it is irrelevant?

I would also argue that if a particular detail is a stumbling block
for someone to understand something it is not that irrelevant
and that claiming something is inconsistent while it is not,
is not a good way to remove such a stumbling block.

Why don't you pick something that really bothers people and see if your
skills (that I'm sure exist) can be of use there?


This did bother someone, it was a stumbling block for him understanding
what was going on.

--
Antoon Pardon
Jul 18 '05 #31
> It doesn't. As Alex has already explained, the above is equivallent to:

def h(): pass

class A:
l = []
f = h

a = A()
print a.l is A.l
print a.f is A.f
So what - the difference is between bound and unbound method, which is what
were talking here about after all - so in the end, its a question of how a
bound method gets created. I'm pretty sure there are plenty of other ways
to create one - try the new module, metaclasses and what not. But that they
exist and are different from unbound methods or functions is not
inconsistent. In the same spirit you could call instance methods in
languages like java or c++ inconsistent - as the have an implicit first
argument, which "normal" functions don't have. So either way round - its a
bit of magic for having oo-style method dispatch. If you want to get rid of
it, don't use OO or at least don't use classes. Nobody prevents you from
doing that.

If I told you that this detail, well not this particular one but
one that is close to it, will break one of my applications in
the transition from python 2.3 to 2.4, do you still think
it is irrelevant?
If its not _this_ detail, its not relevant for _this_ thread. And a general
assertion that transitional changes between versions of python create
problems might be worth a discussion - but that's not what were talking
about here. Instead, we're talking about inconsistencies in _one_ certain
version of python - inconsistencies that no one except you seems to
perceive.

I would also argue that if a particular detail is a stumbling block
for someone to understand something it is not that irrelevant
and that claiming something is inconsistent while it is not,
is not a good way to remove such a stumbling block.
The OP very well understood the difference between bound and unbound
methods. His confusion was that there was no general currying mechanism
behind it that would create subsequent argument bindings if he stuffed a
method into another class. He now understands better. This did bother someone, it was a stumbling block for him understanding
what was going on.


It did bother him because he didn't understand it in the first place - and
he now does understand it.

Well, I'm well prepared to agree to disagree with you on this. If you feel
its inconsistent, I'm not trying to convince you otherwise. But as I said
before: Even if it _is_ - its still of no practical impact. Also the OP
didn't have any further problems after seeing whats getting on. So lets
move along.

--
Regards,

Diez B. Roggisch
Jul 18 '05 #32

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

99
5819
by: David MacQuigg | last post by:
I'm not getting any feedback on the most important benefit in my proposed "Ideas for Python 3" thread - the unification of methods and functions. Perhaps it was buried among too many other less...
3
1981
by: Steven D'Aprano | last post by:
I've been doing a lot of reading about static methods in Python, and I'm not exactly sure what they are useful for or why they were introduced. Here is a typical description of them, this one...
0
1315
by: lc | last post by:
Actually, I have things working but am not clear why do they work. Here's the setup: 3 projects 1. Data component (DataAuth) with connection, adapter and typed dataset (DSAuthors). Two methods,...
8
2032
by: Michael McDowell | last post by:
I'm confused: "why do we need to assign a method to a delegate then assign the delegate to an event why not just assign the method to the events event handler" and "how does making a...
8
1572
by: Rachel Suddeth | last post by:
I'm trying to use reflection to create an object at runtime where the type is given by a string. I thought we should be able to do that, but so far it's not working. I'm trying to work on...
1
1160
by: Neo | last post by:
Is it because of perfomance or something else? I was confused when to use static methods and when to use instance. Please give me some points. Thanks.
3
2153
by: redefined.horizons | last post by:
I've been reading about Python Classes, and I'm a little confused about how Python stores the state of an object. I was hoping for some help. I realize that you can't create an empty place holder...
7
4065
by: mirandacascade | last post by:
O/S: Windows XP Home Vsn of Python: 2.4 Copy/paste of interactive window is immediately below; the text/questions toward the bottom of this post will refer to the content of the copy/paste ...
3
1762
by: rickeringill | last post by:
Hi comp.lang.javascript, I'm throwing this in for discussion. First up I don't claim to be any sort of authority on the ecmascript language spec - in fact I'm a relative newb to these more...
7
1503
by: Pep | last post by:
I'm getting weird results at the moment so thought I'd rebase my knowledge of c++ storage with your help :) I have a class used as a type in a struct and the struct is handled by a 3rd party...
0
7265
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
7388
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
7539
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
5692
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
1
5095
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 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 a new...
0
4751
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...
0
3228
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
807
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
0
461
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.