Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #99485

Re: list slice and generators

From Pavlos Parissis <pavlos.parissis@gmail.com>
Newsgroups comp.lang.python
Subject Re: list slice and generators
Date 2015-11-25 21:43 +0100
Message-ID <mailman.93.1448484205.20593.python-list@python.org> (permalink)
References <5654D8CE.2020105@gmail.com> <n3418c$k41$1@ger.gmane.org>

Show all headers | View raw


[Multipart message — attachments visible in raw view] - view raw

On 25/11/2015 11:07 πμ, Peter Otten wrote:
> Pavlos Parissis wrote:
> 
>> Hi,
>>
>> Do you see any possible dangerous hidden bug in the below code(using
>> python2.7 and python3.4)?
>>
>> My goal is to avoid go through the metrics list twice. But, I don't
>> know if there will be a problem with doing in place replace of list
>> elements using 2 generators.
>>
>> # metrics = ['', '0', '10'....]
>> metrics = [x.metric(name) for x in self._server_per_proc]
>> metrics[:] = (converter(x) for x in metrics)
>> metrics[:] = (x for x in metrics if x is not None)
> 
> Both generators are executed immediately, and the right side is always 
> evaluated before the the slice assignment. Try
> 

This is what I was vaguely remembering, thanks for the confirmation.

> metrics = (x.metric(name) for x in self._server_per_proc)
> metrics = (converter(x) for x in metrics)
> metrics = [x for x in metrics if x is not None]
> 

I see you prefer to bind the result of the evaluation to the same
variable. I learned (the hard way) that it could lead to problems where::

In [1]: a = [1, 2, 3]

In [2]: b = a

In [3]: a == b, a is b
Out[3]: (True, True)

In [4]: a = (x for x in a if x >1)

In [5]: a == b, a is b
Out[5]: (False, False)

In [6]: a
Out[6]: <generator object <genexpr> at 0x7f7f8b7400d8>

In [7]: list(a)
Out[7]: [2, 3]

In [8]: a = [1, 2, 3]

In [9]: b = a

In [10]: a == b, a is b
Out[10]: (True, True)

In [11]: a = [x for x in a if x >1]

In [12]: a == b, a is b
Out[12]: (False, False)

In [13]: a
Out[13]: [2, 3]

In [14]: b
Out[14]: [1, 2, 3]

Thus, I always use slice assignment, even when above case isn't applied.

> or
> 
> metrics = (converter(x.metric(name)) for x in self._server_per_proc)
> metrics = [x for x in metrics if x is not None]
> 

I should do the above.

> to get down to one intermediate list. Avoiding the last one is a bit tricky:
> 
> metrics = (converter(x.metric(name)) for x in self._server_per_proc)
> metrics = (x for x in metrics if x is not None)
> try:
>     # if there is at least one item the generator is not empty
>     first = next(metrics)
> except StopIteration:
>     metrics = ()
> else:
>     # put the first item back in
>     metrics = itertools.chain([first], metrics)
>     assert metrics
> 

Tricky, indeed

Thanks for your time and effort to answer my question, it is very
much appreciated.

Cheers,
Pavlos

Back to comp.lang.python | Previous | Next | Find similar | Unroll thread


Thread

Re: list slice and generators Pavlos Parissis <pavlos.parissis@gmail.com> - 2015-11-25 21:43 +0100

csiph-web