Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #56500 > unrolled thread
| Started by | Marco Buttu <marco.buttu@gmail.com> |
|---|---|
| First post | 2013-10-09 17:44 +0200 |
| Last post | 2013-10-11 08:15 +0200 |
| Articles | 11 — 5 participants |
Back to article view | Back to comp.lang.python
super in Python 3 and variadic arguments Marco Buttu <marco.buttu@gmail.com> - 2013-10-09 17:44 +0200
Re: super in Python 3 and variadic arguments Ned Batchelder <ned@nedbatchelder.com> - 2013-10-09 12:47 -0400
Re: super in Python 3 and variadic arguments Marco Buttu <marco.buttu@gmail.com> - 2013-10-10 09:22 +0200
Re: super in Python 3 and variadic arguments Ned Batchelder <ned@nedbatchelder.com> - 2013-10-10 07:04 -0400
Re: super in Python 3 and variadic arguments Marco Buttu <marco.buttu@gmail.com> - 2013-10-10 14:54 +0200
Re: super in Python 3 and variadic arguments Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-10-11 02:11 +0000
Re: super in Python 3 and variadic arguments Ian Kelly <ian.g.kelly@gmail.com> - 2013-10-10 20:33 -0600
Re: super in Python 3 and variadic arguments Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-10-11 03:00 +0000
Re: super in Python 3 and variadic arguments Chris Angelico <rosuav@gmail.com> - 2013-10-11 17:08 +1100
Re: super in Python 3 and variadic arguments Marco Buttu <marco.buttu@gmail.com> - 2013-10-11 08:17 +0200
Re: super in Python 3 and variadic arguments Marco Buttu <marco.buttu@gmail.com> - 2013-10-11 08:15 +0200
| From | Marco Buttu <marco.buttu@gmail.com> |
|---|---|
| Date | 2013-10-09 17:44 +0200 |
| Subject | super in Python 3 and variadic arguments |
| Message-ID | <l33tlf$rr1$1@speranza.aioe.org> |
Given this class: >>> class A: ... def afoo(*args): ... print(args) in Python 3 we can write the following class: >>> class B(A): ... def bfoo(*args): ... super(B, args[0]).afoo(*args[1:]) ... >>> B().bfoo(1, 2, 3) (<__main__.B object at 0x7f5b3bde48d0>, 1, 2, 3) without giving arguments to super, in this way: >>> class B(A): ... def bfoo(self, *args): ... super().afoo(*args) ... >>> B().bfoo(1, 2, 3) (<__main__.B object at 0x7f5b3bdea0d0>, 1, 2, 3) But it does not work in this case: >>> class B(A): ... def bfoo(*args): ... super().afoo(*args[1:]) ... >>> B().bfoo(1, 2, 3) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 3, in bfoo RuntimeError: super(): no arguments How come? -- Marco Buttu
[toc] | [next] | [standalone]
| From | Ned Batchelder <ned@nedbatchelder.com> |
|---|---|
| Date | 2013-10-09 12:47 -0400 |
| Message-ID | <mailman.902.1381337680.18130.python-list@python.org> |
| In reply to | #56500 |
On 10/9/13 11:44 AM, Marco Buttu wrote: > Given this class: > > >>> class A: > ... def afoo(*args): > ... print(args) > > in Python 3 we can write the following class: > > >>> class B(A): > ... def bfoo(*args): > ... super(B, args[0]).afoo(*args[1:]) > ... > >>> B().bfoo(1, 2, 3) > (<__main__.B object at 0x7f5b3bde48d0>, 1, 2, 3) > > > without giving arguments to super, in this way: > > >>> class B(A): > ... def bfoo(self, *args): > ... super().afoo(*args) > ... > >>> B().bfoo(1, 2, 3) > (<__main__.B object at 0x7f5b3bdea0d0>, 1, 2, 3) > > But it does not work in this case: > > >>> class B(A): > ... def bfoo(*args): > ... super().afoo(*args[1:]) > ... > >>> B().bfoo(1, 2, 3) > Traceback (most recent call last): > File "<stdin>", line 1, in <module> > File "<stdin>", line 3, in bfoo > RuntimeError: super(): no arguments > > How come? The no-args super() call inspects the calling environment to determine the class and self. "self" is the first local name stored in frame.f_code.co_localsplus, but *args doesn't put "args" into that entry of the code object. Basically, super() is looking for the first regular argument in the function. --Ned.
[toc] | [prev] | [next] | [standalone]
| From | Marco Buttu <marco.buttu@gmail.com> |
|---|---|
| Date | 2013-10-10 09:22 +0200 |
| Message-ID | <52565598.6000709@gmail.com> |
| In reply to | #56504 |
On 10/09/2013 06:47 PM, Ned Batchelder wrote: >> >>> class B(A): >> ... def bfoo(*args): >> ... super().afoo(*args[1:]) >> ... >> >>> B().bfoo(1, 2, 3) >> Traceback (most recent call last): >> File "<stdin>", line 1, in <module> >> File "<stdin>", line 3, in bfoo >> RuntimeError: super(): no arguments >> >> How come? > > The no-args super() call inspects the calling environment to determine > the class and self. "self" is the first local name stored in > frame.f_code.co_localsplus, but *args doesn't put "args" into that entry > of the code object But is it a bug or the behavior we want? The first (implicit) argument is stored as expected as the first one in the args tuple, and the args tuple is inserted as expected in frame.f_locals: >>> import inspect >>> class B(A): ... def bfoo(*args): ... frame = inspect.currentframe() ... for obj, value in frame.f_locals.items(): ... print(obj, value, sep=' --> ') ... # super().afoo(*args[1:]) ... >>> B().bfoo(1, 2, 3) args --> (<__main__.B object at 0x7f28c960a590>, 1, 2, 3) frame --> <frame object at 0x7f28cad4b240> So, why does not super use it? -- Marco Buttu
[toc] | [prev] | [next] | [standalone]
| From | Ned Batchelder <ned@nedbatchelder.com> |
|---|---|
| Date | 2013-10-10 07:04 -0400 |
| Message-ID | <mailman.932.1381403081.18130.python-list@python.org> |
| In reply to | #56552 |
On 10/10/13 3:22 AM, Marco Buttu wrote:
> On 10/09/2013 06:47 PM, Ned Batchelder wrote:
>
>>> >>> class B(A):
>>> ... def bfoo(*args):
>>> ... super().afoo(*args[1:])
>>> ...
>>> >>> B().bfoo(1, 2, 3)
>>> Traceback (most recent call last):
>>> File "<stdin>", line 1, in <module>
>>> File "<stdin>", line 3, in bfoo
>>> RuntimeError: super(): no arguments
>>>
>>> How come?
>>
>> The no-args super() call inspects the calling environment to determine
>> the class and self. "self" is the first local name stored in
>> frame.f_code.co_localsplus, but *args doesn't put "args" into that entry
>> of the code object
>
> But is it a bug or the behavior we want? The first (implicit) argument
> is stored as expected as the first one in the args tuple, and the args
> tuple is inserted as expected in frame.f_locals:
>
> >>> import inspect
> >>> class B(A):
> ... def bfoo(*args):
> ... frame = inspect.currentframe()
> ... for obj, value in frame.f_locals.items():
> ... print(obj, value, sep=' --> ')
> ... # super().afoo(*args[1:])
> ...
> >>> B().bfoo(1, 2, 3)
> args --> (<__main__.B object at 0x7f28c960a590>, 1, 2, 3)
> frame --> <frame object at 0x7f28cad4b240>
>
> So, why does not super use it?
>
I haven't seen the discussion that decided the behavior of super(), but
I'd guess that if you reported this as a bug, it would be closed as
wontfix, because: 1) the use case you describe isn't something people
actually write, 2) it would add to the complexity of super() to support
it, and 3) there's a simple way to write your code that does work:
class B(A):
def bfoo(self, *args):
super().afoo(*args)
(though it's a bit odd to call afoo from bfoo.)
Python has never claimed the kind of purity that makes everything work
in a totally simple consistent way. super() with no args is a kind of
hack to begin with. It involves a special case in the compiler (so that
using the name "super" as a function call will act as if you had
accessed the name "__class__" so that super can find it later), and
inspecting the stack frame during execution.
It's an interesting case of the Zen of Python. It violates one
("explicit is better than implicit"), but only because of another one
("practicality beats purity"). super(MyClass, self) in Python 2 is the
kind of brain-bender that so many people get wrong at first, that it's
helped plenty of people to do the arguments implicitly, even if there
are oddball edge cases that it doesn't seem to handle properly.
--Ned.
[toc] | [prev] | [next] | [standalone]
| From | Marco Buttu <marco.buttu@gmail.com> |
|---|---|
| Date | 2013-10-10 14:54 +0200 |
| Message-ID | <l3681f$gqh$1@speranza.aioe.org> |
| In reply to | #56558 |
On 10/10/2013 01:04 PM, Ned Batchelder wrote:
> On 10/10/13 3:22 AM, Marco Buttu wrote:
>> >>> import inspect
>> >>> class B(A):
>> ... def bfoo(*args):
>> ... frame = inspect.currentframe()
>> ... for obj, value in frame.f_locals.items():
>> ... print(obj, value, sep=' --> ')
>> ... # super().afoo(*args[1:])
>> ...
>> >>> B().bfoo(1, 2, 3)
>> args --> (<__main__.B object at 0x7f28c960a590>, 1, 2, 3)
>> frame --> <frame object at 0x7f28cad4b240>
>>
>> So, why does not super use it?
>>
>
> Python has never claimed the kind of purity that makes everything work
> in a totally simple consistent way. super() with no args is a kind of
> hack to begin with. It involves a special case in the compiler (so that
> using the name "super" as a function call will act as if you had
> accessed the name "__class__" so that super can find it later), and
> inspecting the stack frame during execution.
It seems reasonable
> It's an interesting case of the Zen of Python. It violates one
> ("explicit is better than implicit"), but only because of another one
> ("practicality beats purity"). super(MyClass, self) in Python 2 is the
> kind of brain-bender that so many people get wrong at first, that it's
> helped plenty of people to do the arguments implicitly, even if there
> are oddball edge cases that it doesn't seem to handle properly.
>
> --Ned.
Thanks for the comprehensive answer ;)
--
Marco Buttu
[toc] | [prev] | [next] | [standalone]
| From | Steven D'Aprano <steve+comp.lang.python@pearwood.info> |
|---|---|
| Date | 2013-10-11 02:11 +0000 |
| Message-ID | <52575e47$0$29984$c3e8da3$5496439d@news.astraweb.com> |
| In reply to | #56558 |
On Thu, 10 Oct 2013 07:04:38 -0400, Ned Batchelder wrote:
> super() with no args is a kind of hack to begin with. It involves a
> special case in the compiler (so that using the name "super" as a
> function call will act as if you had accessed the name "__class__" so
> that super can find it later), and inspecting the stack frame during
> execution.
super() with no arguments is *completely* a hack[1], and one where GvR
has said "Never again!" if I remember correctly. I don't think he regrets
allowing the super compile-time magic, just that it really is magic and
he doesn't want to make a habit of it.
One of the side-effects of this being a hack is that this doesn't work:
class X(Y):
def method(self, arg):
f = super
f().method(arg)
[1] Which is not necessarily a bad thing!
--
Steven
[toc] | [prev] | [next] | [standalone]
| From | Ian Kelly <ian.g.kelly@gmail.com> |
|---|---|
| Date | 2013-10-10 20:33 -0600 |
| Message-ID | <mailman.977.1381458865.18130.python-list@python.org> |
| In reply to | #56632 |
On Thu, Oct 10, 2013 at 8:11 PM, Steven D'Aprano
<steve+comp.lang.python@pearwood.info> wrote:
> One of the side-effects of this being a hack is that this doesn't work:
>
> class X(Y):
> def method(self, arg):
> f = super
> f().method(arg)
Actually, that works just fine. The compiler sees that super is
accessed within the method and creates the closure necessary to make
it work. This does fail, however:
f = super
class X(Y):
def method(self, arg):
f().method(arg)
[toc] | [prev] | [next] | [standalone]
| From | Steven D'Aprano <steve+comp.lang.python@pearwood.info> |
|---|---|
| Date | 2013-10-11 03:00 +0000 |
| Message-ID | <525769b2$0$29984$c3e8da3$5496439d@news.astraweb.com> |
| In reply to | #56634 |
On Thu, 10 Oct 2013 20:33:37 -0600, Ian Kelly wrote: > On Thu, Oct 10, 2013 at 8:11 PM, Steven D'Aprano > <steve+comp.lang.python@pearwood.info> wrote: >> One of the side-effects of this being a hack is that this doesn't work: >> >> class X(Y): >> def method(self, arg): >> f = super >> f().method(arg) > > Actually, that works just fine. The compiler sees that super is > accessed within the method and creates the closure necessary to make it > work. This does fail, however: > > f = super > class X(Y): > def method(self, arg): > f().method(arg) Ah, that's the one! Thanks for the correction. I'll now go and write "I will always test my code snippets before posting" on the blackboard one hundred times. -- Steven
[toc] | [prev] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2013-10-11 17:08 +1100 |
| Message-ID | <mailman.985.1381471733.18130.python-list@python.org> |
| In reply to | #56638 |
On Fri, Oct 11, 2013 at 2:00 PM, Steven D'Aprano
<steve+comp.lang.python@pearwood.info> wrote:
> I'll now go and write "I will always test my code snippets before
> posting" on the blackboard one hundred times.
print("I will always test my code snippets before posting\n"*100)
ChrisA
PS. Irony would be having a bug in that because I didn't test it. I
almost didn't, but remembered just before hitting Send.
[toc] | [prev] | [next] | [standalone]
| From | Marco Buttu <marco.buttu@gmail.com> |
|---|---|
| Date | 2013-10-11 08:17 +0200 |
| Message-ID | <52579809.1040904@gmail.com> |
| In reply to | #56634 |
On 10/11/2013 04:33 AM, Ian Kelly wrote: > On Thu, Oct 10, 2013 at 8:11 PM, Steven D'Aprano >> >One of the side-effects of this being a hack is that this doesn't work: >> > >> >class X(Y): >> > def method(self, arg): >> > f = super >> > f().method(arg) > Actually, that works just fine. The compiler sees that super is > accessed within the method and creates the closure necessary to make > it work. This does fail, however: > > f = super > class X(Y): > def method(self, arg): > f().method(arg) Very interesting! Thanks :) -- Marco Buttu
[toc] | [prev] | [next] | [standalone]
| From | Marco Buttu <marco.buttu@gmail.com> |
|---|---|
| Date | 2013-10-11 08:15 +0200 |
| Message-ID | <l3851l$tbo$1@speranza.aioe.org> |
| In reply to | #56632 |
On 10/11/2013 04:11 AM, Steven D'Aprano wrote: > super() with no arguments is*completely* a hack[1], and one where GvR > has said "Never again!" if I remember correctly. I don't think he regrets > allowing the super compile-time magic, just that it really is magic and > he doesn't want to make a habit of it. > ... > [1] Which is not necessarily a bad thing! Thanks a lot for this anecdote :) -- Marco Buttu
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.python
csiph-web