Re: [Python-ideas] Keyword for direct pass through of kwargs to super

2018-05-27 Thread Greg Ewing

Michael Lohmann wrote:


class Magic:
magic_number = 42
def __init__(self):
A.magic_number = 0  # As soon as you look too deep into it all the 
Magic vanishes


What is A here? Did you mean something else?

--
Greg
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Proposal: A Reduce-Map Comprehension and a "last" builtin

2018-05-27 Thread Greg Ewing

Nick Coghlan wrote:
Aye, while I still don't want comprehensions to implicitly create new 
locals in their parent scope, I've come around on the utility of letting 
inline assignment targets be implicitly nonlocal references to the 
nearest block scope.


What if you're only intending to use it locally within the
comprehension? Would you have to put a dummy assignment in
the surrounding scope to avoid a NameError? That doesn't
sound very nice.

--
Greg
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Keyword for direct pass through of kwargs to super

2018-05-27 Thread Michael Lohmann

> Everything my idea has to offer really is just reasonable if you don’t have 
> single inheritance only

I would like to correct myself immediately on that one: In the Pizza-example 
(from yesterday as well) it would be possible to overwrite the default price of 
the HawaiianPizza with the merging of bypassed kwargs with the ones from the 
call itself. Let us assume that the exemption of the 10$ price for all 
HawaiianPizzas would be a Family-sized pizza for 20$:

class Pizza:
def __init__(self, *, size, price):
print("The price of this %s pizza is:", (size, price))

@cooperative
class HawaiianPizza(Pizza):
def __init__(self, *, pineapple="chunked", size=8):
print("This pizza has %s pineapple." % pineapple)
super().__init__(price=10, size=size)

class FamilyHawaiianPizza(HawaiianPizza):
def __init__(self, *, pineapple="chunked"):
super().__init__(price=20, size=20, pineapple=pineapple) #This 
would overwrite the price of the HawaiianPizza

But this would not be the real intention of the usage, but just a side effect 
of correctly handling a simple diamond-like hierarchy. The reason that bypassed 
kwargs should overwrite them is that they come from up the MRO and so obviously 
should have priority.

Sorry to spam you all,
Have a nice Sunday! Michael
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Keyword for direct pass through of kwargs to super

2018-05-27 Thread Michael Lohmann
I realized that bypassing kwargs is probably the least important thing of this 
idea - so if implemented it definitely had to get a better name. Just look at 
the following example:

class Magic:
magic_number = 42
def __init__(self):
A.magic_number = 0  # As soon as you look too deep into it all the 
Magic vanishes

class Foo(Magic):
def __init__(self):
print("foo")
# Let's say we want magic_number==42 in Foo
# So you can’t call super().__init__ here if it is not in the 
middle of an MRO
# Technically you could get it working by going to the first init 
in the MRO of self after Foo \
# that isn’t in the MRO of Foo but you can see that this gets 
quite ugly to write (and read!).
# And then you would still have the problem of indicating that Foo 
seems to accepted kwargs as input

class Bar:
def __init__(self, bar):
print("bar:", bar)

class FooBar(Foo, Bar):
def __init__(self):
# There is no easy way right now to avoid writing
Foo.__init__()
Bar.__init__(bar="bar“)

But if Foo adopted this protocol of "automated MRO handling"/"cooperativity" 
(or however you want to call it) Bar.__init__ could be called automatically. 
What do I mean by that? Well, basically do automatically what I described in 
the comment of Foo if no super().__init__ call was registered in any 
cooperative class.

Okay, this example might be a bit far-fetched, but it shows, that you could 
easily get the MRO working as expected with a simple 
super().__init__(bar="bar") in FooBar.



> This shouldn't be a problem if each method along the way
> absorbs all the arguments it knows about, and only passes
> on the ones it doesn’t.
Two remarks: 1) Everything my idea has to offer really is just reasonable if 
you don’t have single inheritance only and 2) This wasn’t really my problem 
with the current status (in fact: the way I would tackle this problem would 
also only work if all kwargs get fully consumed). But:

What bugs me is that in my example from yesterday (
   class Aardvark:
   def __init__(self, quantity, **kwargs):
   print("There is some quantity:", quantity)
   # I actually don’t care about **kwargs and just hand them on
   super().__init__(**kwargs)

   class Clever:
   def __init__(self, cleverness=1):
   print("You are %d clever“ % cleverness)

   class Ethel(Aardvark, Clever):
   """Ethel is a very clever Aardvark"""
   def __init__(self):
   super().__init__(quantity="some spam", cleverness=1000)
) if you want to instantiate an Aardvark directly there is NO WAY EVER that you 
could give him any kwargs. So why should the __init__ indicate something else? 
Well, just to make the MRO work. All I want is to make it as obvious as 
possible that an Aardvark ONLY takes `quantity` as input, but is fully 
"cooperative" with other classes if it is in the middle of the MRO (by which I 
mean that it will automatically call the __init__ and hand on any kwargs it 
didn’t expect to a class from a different branch of the class hierarchy).
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Keyword for direct pass through of kwargs to super

2018-05-27 Thread Greg Ewing

Brendan Barnwell wrote:

If I understand correctly, the essence of your argument seems to be 
that you want be able to write a class A, and you want to be able to use 
that class EITHER as the top of an inheritance chain (i.e., have it 
inherit directly from object) OR in the middle of an inheritance chain 
(i.e., inheriting from some other class, but not object).


This shouldn't be a problem if each method along the way
absorbs all the arguments it knows about, and only passes
on the ones it doesn't. E.g.

class A:
def __init__(self, alpha, **kwds):
print("alpha =", alpha)
super().__init__(**kwds)

class B(A):
def __init__(self, beta, **kwds):
print("beta =", beta)
super().__init__(**kwds)

b = B(alpha = 17, beta = 42)

Both A and B here pass on a **kwds argument, but by the
time it get to object, there are no arguments left, so
it's fine.

--
Greg

___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Proposal: A Reduce-Map Comprehension and a "last" builtin

2018-05-27 Thread Nick Coghlan
On 26 May 2018 at 04:14, Tim Peters  wrote:

> [Peter O'Connor]
> >> ...
> >> We could use given for both the in-loop variable update and the variable
> >> initialization:
> >>smooth_signal =  [average given average=(1-decay)*average + decay*x
> >> for x in signal] given average=0.
>
> [Steven D'Aprano ]
> > I don't think that will work under Nick's proposal, as Nick does not
> > want assignments inside the comprehension to be local to the surrounding
> > scope. (Nick, please correct me if I'm wrong.)
>
> Nick appears to have moved on from "given" to more-general augmented
> assignment expressions.


Aye, while I still don't want comprehensions to implicitly create new
locals in their parent scope, I've come around on the utility of letting
inline assignment targets be implicitly nonlocal references to the nearest
block scope.


>   See PEP 577, but note that it's still a
> work-in-progress:
>
> https://github.com/python/peps/pull/665
>
>
> Under that PEP,
>
> average = 0
> smooth_signal =  [(average := (1-decay)*average + decay*x)
>  for x in signal]
>
> Or, for the running sums example:
>
> total = 0
> sums = [(total += x) for x in data]
>
> I'm not entirely clear on whether the "extra" parens are needed, so
> added 'em anyway to make grouping clear.
>

I think the parens would technically be optional (as in PEP 572), since
"EXPR for" isn't legal syntax outside parentheses/brackets/braces, so the
parser would terminate the assignment expression when it sees the "for"
keyword.

Cheers,
Nick.

-- 
Nick Coghlan   |   ncogh...@gmail.com   |   Brisbane, Australia
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Keyword for direct pass through of kwargs to super

2018-05-27 Thread Michael Lohmann

>   If I understand correctly, the essence of your argument seems to be 
> that you want be able to write a class A, and you want to be able to use that 
> class EITHER as the top of an inheritance chain (i.e., have it inherit 
> directly from object) OR in the middle of an inheritance chain (i.e., 
> inheriting from some other class, but not object).
Well, it does not necessarily inherit from object, but from any class, that 
does not accept any more kwargs. E.g.  if you have a diamond structure as your 
class-hierachy then one branch could forward information to the second (if you 
understand what I mean?).

> But I don't really see how your solution of magically making kwargs appear 
> and disappear is a good solution to that problem.

I intended the following text for the python-list mailing-list, but it I think 
I might have structured my ideas a bit better than in my previous messages and 
the summary in __Reason__ might tackle why this could be a nice idea (spoiler: 
make super even more super by doing things if it is NOT there in a clever 
manner).


Let us start with a simple class:
class Aardvark:
def __init__(self, quantity):
print("There is some quantity:", quantity)


Well, that works nicely and we can go and send our Aardvark to survey some 
quantities. But if we now want to get the multi-inheritance to work properly we 
need to change it to:

class Aardvark:
def __init__(self, quantity, **kwargs):
print("There is some quantity:", quantity)
# I actually don’t care about **kwargs and just hand them on
super().__init__(**kwargs)

class Clever:
def __init__(self, cleverness=1):
print("You are %d clever“ % cleverness)

class Ethel(Aardvark, Clever):
"""Ethel is a very clever Aardvark"""
def __init__(self):
super().__init__(quantity="some spam", cleverness=1000)

But if you now look at the declaration of the Aardvark .__init__, it seems like 
you could instantiate it with **kwargs. This in fact is not true. As soon as 
you create a direct instance of Aardvark, `object` as the super() doesn’t 
accept any kwargs. So basically I think that the parameters for the init should 
just say `quantity ` while still preserving the functionality.

Now that obviously doesn’t work until now. But could you add something that 
lets this class tell the interpreter instead: "Hey, could you just forward 
anything that this init doesn’t need to super().__init__" ? I have something 
like this in mind:

class Aardvark:
@bypass_kwargs_to_super
def __init__(self, *, quantity):
print("There is some quantity:", quantity)
super().__init__()

This would collect everything "behind the scenes" that usually **kwargs would 
have collected and "append" it to the super call. Question: If Aardvark knows 
that he really does not need the kwargs himself: why give them to him in the 
first place? I mean, I trust him - he seems like a very nice guy, but he might 
have accidentally forgotten to forward them unintentionally.

You would obviously still be able to use **kwargs the usual way but then you 
couldn’t use this technique and would need to take care of passing down all the 
information to super() yourself as usual.


__Reason__: With something like this it is immediately obvious that Aardvark 
ONLY takes `quantity` as an input if you instantiate it directly but if 
subclassed it is able to hand information down the MRO to something from a 
different "Branch". And in addition to the better human readability: any form 
of automated docstring-genaration now can be certain that you don’t do anything 
with (or to) the **kwargs (since the init doesn’t get them in the first place). 
In addition it could make super even more super by doing something if it is NOT 
there as proposed in the second of the the following problems.

Of course you need to be quite clever to do this properly, for example
1) What to do if there are collisions between the bypassed kwargs and the ones 
from the init call? - Probably keep the ones you bypassed since they come from 
the top of the MRO
2) What do you do if super().__init__ was not called? The most clever thing 
would be to go „up and to the next branch“ of the inheritance diagram. As in: 
if Aardvark is a Subclass of Animal, don’t call its init but directly Clevers - 
(you would have to look up the MRO of the super of Aardvark and skip them in 
the Ethel MRO before calling the next init automatically).

In theory you could also add something that forwards *args as well but the 
usage of that is probably much more limited...

On thing that might look a bit strange is that you actually could actually pass 
in additional kwargs despite the init saying otherwise:
`Aardvark(quantity='some spam', something="Object will throw an error now 
unexpected kwarg")`
and this would then throw an error that "object (instead of Aardvark) does 

Re: [Python-ideas] Keyword for direct pass through of kwargs to super

2018-05-27 Thread Brendan Barnwell

On 2018-05-26 02:22, Michael Lohmann wrote:

Whenever you give any kwargs when directly instantiating `A` they
will be passed down to super which in this case is `object`. And now
to the follow-up question: Can you tell me which kwargs object takes
as an input for it’s __init__? So does it EVER make ANY sense to
specify them if you DIRECTLY create an instance of `A`?

But now let’s say your MRO is `SuperClass, A, B`, then A should
better be able to forward the kwargs, so currently you need to
directly hand them to `A` and rely on the fact that it passes them on
to `B`.


	If I understand correctly, the essence of your argument seems to be 
that you want be able to write a class A, and you want to be able to use 
that class EITHER as the top of an inheritance chain (i.e., have it 
inherit directly from object) OR in the middle of an inheritance chain 
(i.e., inheriting from some other class, but not object).  But you 
can't, because if you pass on extra **kwargs, that will fail if the 
class inherits directly from object, but if you don't pass on extra 
**kwargs, that will fail if the class doesn't inherit directly from 
object.  Is that correct?


	I agree that it is somewhat somewhat awkward that "is this the top 
class in the hierarchy" is something that has to be known when writing a 
class.  I think this would be ameliorated by having "object" accept and 
ignore extra arguments.  (I seem to recall that was decided to be a bad 
idea at some time in the past, though.)  But I don't really see how your 
solution of magically making kwargs appear and disappear is a good 
solution to that problem.


--
Brendan Barnwell
"Do not follow where the path may lead.  Go, instead, where there is no
path, and leave a trail."
   --author unknown
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/