> On Feb 9, 2015, at 7:29 PM, Neil Girdhar <mistersh...@gmail.com> wrote:
> 
> For some reason I can't seem to reply using Google groups, which is is 
> telling "this is a read-only mirror" (anyone know why?)  Anyway, I'm going to 
> answer as best I can the concerns.
> 
> Antoine said:
> 
> To be clear, the PEP will probably be useful for one single line of 
> Python code every 10000. This is a very weak case for such an intrusive 
> syntax addition. I would support the PEP if it only added the simple 
> cases of tuple unpacking, left alone function call conventions, and 
> didn't introduce **-unpacking. 
> 
> To me this is more of a syntax simplification than a syntax addition.  For me 
> the **-unpacking is the most useful part. Regarding utility, it seems that a 
> many of the people on r/python were pretty excited about this PEP: 
> http://www.reddit.com/r/Python/comments/2synry/so_8_peps_are_currently_being_proposed_for_python/
>  
> <http://www.reddit.com/r/Python/comments/2synry/so_8_peps_are_currently_being_proposed_for_python/>
> 
> —
> 
> Victor noticed that there's a mistake with the code:
> 
> >>> ranges = [range(i) for i in range(5)] 
> >>> [*item for item in ranges] 
> [0, 0, 1, 0, 1, 2, 0, 1, 2, 3] 
> 
> It should be a range(4) in the code.  The "*" applies to only item.  It is 
> the same as writing:
> 
> [*range(0), *range(1), *range(2), *range(3), *range(4)]
> 
> which is the same as unpacking all of those ranges into a list.
> 
> > function(**kw_arguments, **more_arguments) 
> If the key "key1" is in both dictionaries, more_arguments wins, right? 
> 
> There was some debate and it was decided that duplicate keyword arguments 
> would remain an error (for now at least).  If you want to merge the 
> dictionaries with overriding, then you can still do:
> 
> function(**{**kw_arguments, **more_arguments})
> 
> because **-unpacking in dicts overrides as you guessed.
> 
> —
> 
> 
> 
> On Mon, Feb 9, 2015 at 7:12 PM, Donald Stufft <don...@stufft.io 
> <mailto:don...@stufft.io>> wrote:
> 
>> On Feb 9, 2015, at 4:06 PM, Neil Girdhar <mistersh...@gmail.com 
>> <mailto:mistersh...@gmail.com>> wrote:
>> 
>> Hello all,
>> 
>> The updated PEP 448 (https://www.python.org/dev/peps/pep-0448/ 
>> <https://www.python.org/dev/peps/pep-0448/>) is implemented now based on 
>> some early work by Thomas Wouters (in 2008) and Florian Hahn (2013) and 
>> recently completed by Joshua Landau and me.
>> 
>> The issue tracker http://bugs.python.org/issue2292 
>> <http://bugs.python.org/issue2292>  has  a working patch.  Would someone be 
>> able to review it?
>> 
> 
> I just skimmed over the PEP and it seems like it’s trying to solve a few 
> different things:
> 
> * Making it easy to combine multiple lists and additional positional args 
> into a function call
> * Making it easy to combine multiple dicts and additional keyword args into a 
> functional call
> * Making it easy to do a single level of nested iterable "flatten".
> 
> I would say it's:
> * making it easy to unpack iterables and mappings in function calls
> * making it easy to unpack iterables  into list and set displays and 
> comprehensions, and
> * making it easy to unpack mappings into dict displays and comprehensions.
> 
>  
> 
> Looking at the syntax in the PEP I had a hard time detangling what exactly it 
> was doing even with reading the PEP itself. I wonder if there isn’t a way to 
> combine simpler more generic things to get the same outcome.
> 
> Looking at the "Making it easy to combine multiple lists and additional 
> positional args into a  function call" aspect of this, why is:
> 
> print(*[1], *[2], 3) better than print(*[1] + [2] + [3])?
> 
> That's already doable in Python right now and doesn't require anything new to 
> handle it.
> 
> Admittedly, this wasn't a great example.  But, if [1] and [2] had been 
> iterables, you would have to cast each to list, e.g.,
> 
> accumulator = []
> accumulator.extend(a) 
> accumulator.append(b)
> accumulator.extend(c)
> print(*accumulator)
> 
> replaces
> 
> print(*a, b, *c)
> 
> where a and c are iterable.  The latter version is also more efficient 
> because it unpacks only a onto the stack allocating no auxilliary list.

Honestly that doesn’t seem like the way I’d write it at all, if they might not 
be lists I’d just cast them to lists:

print(*list(a) + [b] + list(c))

But if casting to list really is that big a deal, then perhaps a better 
solution is to simply make it so that something like ``a_list + an_iterable`` 
is valid and the iterable would just be consumed and +’d onto the list. That 
still feels like a more general solution and a far less surprising and easier 
to read one.


> 
> 
> Looking at the "making it easy to do a single level of nsted iterable 
> 'flatten'"" aspect of this, the example of:
> 
> >>> ranges = [range(i) for i in range(5)]
> >>> [*item for item in ranges]
> [0, 0, 1, 0, 1, 2, 0, 1, 2, 3]
> 
> Conceptually a list comprehension like [thing for item in iterable] can be 
> mapped to a for loop like this:
> 
> result = []
> for item in iterable:
>     result.append(thing)
> 
> However [*item for item in ranges] is mapped more to something like this:
> 
> result = []
> for item in iterable:
>     result.extend(*item)
> 
> I feel like switching list comprehensions from append to extend just because 
> of a * is really confusing and it acts differently than if you just did *item 
> outside of a list comprehension. I feel like the itertools.chain() way of 
> doing this is *much* clearer.
> 
> Finally there's the "make it easy to combine multiple dicts into a function 
> call" aspect of this. This I think is the biggest thing that this PEP 
> actually adds, however I think it goes around it the wrong way. Sadly there 
> is nothing like [1] + [2] for dictionaries. The closest thing is:
> 
> kwargs = dict1.copy()
> kwargs.update(dict2)
> func(**kwargs)
> 
> So what I wonder is if this PEP wouldn't be better off just using the 
> existing methods for doing the kinds of things that I pointed out above, and 
> instead defining + or | or some other symbol for something similar to [1] + 
> [2] but for dictionaries. This would mean that you could simply do:
> 
> func(**dict1 | dict(y=1) | dict2)
> 
> instead of
> 
> dict(**{'x': 1}, y=2, **{'z': 3})
> 
> I feel like not only does this genericize way better but it limits the impact 
> and new syntax being added to Python and is a ton more readable.


Honestly the use of * and ** in functions doesn’t bother me a whole lot, though 
i don’t see much use for it over what’s already available for lists (and I 
think doing something similarly generic for mapping is a better idea). What 
really bothers me is these parts:

* making it easy to unpack iterables  into list and set displays and 
comprehensions, and
* making it easy to unpack mappings into dict displays and comprehensions.

I feel like these are super wrong and if they were put in I’d probably end up 
writing a linter to disallow them in my own code bases.

I feel like adding a special case for * in list comprehensions breaks the 
“manually expanded” version of those. Switching from append to extend inside of 
a list comprehension because of a * doesn’t make any sense to me. I can’t seem 
to construct any for loop that mimics what this PEP proposes as [*item for item 
in iterable] without fundamentally changing the operation that happens in each 
loop of the list comprehension.


---
Donald Stufft
PGP: 7C6B 7C5D 5E2B 6356 A926 F04F 6E3C BCE9 3372 DCFA

_______________________________________________
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com

Reply via email to