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. 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.
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
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.
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.
> 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
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
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
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.
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.
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
> 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
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
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
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
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
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-----
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
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-----
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
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
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
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
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.
"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>
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
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
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
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
> 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
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
> 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 This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics |
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...
|
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...
|
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,...
|
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...
|
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...
| |
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.
|
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...
|
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
...
|
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...
|
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...
|
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,...
| |
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,...
|
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...
|
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,...
|
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...
|
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...
|
by: adsilva |
last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
| |
by: muto222 |
last post by:
How can i add a mobile payment intergratation into php mysql website.
|
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...
| |