list slice and generators
Peter Otten
__peter__ at web.de
Wed Nov 25 05:07:08 EST 2015
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
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]
or
metrics = (converter(x.metric(name)) for x in self._server_per_proc)
metrics = [x for x in metrics if x is not None]
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
> return calculate(name, metrics)
>
>
> def calculate(name, metrics):
> if not metrics:
> return None
>
> if name in METRICS_SUM:
> return sum(metrics)
> elif name in METRICS_AVG:
# writing a function that calculates the average without
# materialising the list left as an exercise ;)
metrics = list(metrics)
> return int(sum(metrics)/len(metrics))
> else:
> raise ValueError("Unknown type of calculation for
> {}".format(name))
>
>
> def converter(value):
> try:
> return int(float(value))
> except ValueError:
> return value.strip() or None
> except TypeError:
> return None
Disclaimer: all code untested.
More information about the Python-list
mailing list