for loop over function that returns a tuple?
Steven D'Aprano
steve at pearwood.info
Wed Sep 2 10:49:35 EDT 2015
On Wed, 2 Sep 2015 09:49 pm, Victor Hooi wrote:
> I have a function which is meant to return a tuple:
>
> def get_metrics(server_status_json, metrics_to_extract, line_number):
> <SOME_CODE>
> return ((timestamp, "serverstatus", values, tags))
No need for the second pair of parentheses. Technically, no need for any
parens, this will do:
return timestamp, "serverstatus", values, tags
but putting a single pair of parens around the four items is acceptable for
aesthetic reasons.
> I also have:
>
> def create_point(timestamp, metric_name, values, tags):
This function requires four separate values. So you have to either pass four
values, using tuple unpacking, or re-write the function to accept a single
tuple, then unpack it inside the function:
def create_point(items):
timestamp, metric_name, values, tags = items
...
Another possibility is to be clever (perhaps too clever?) and accept either
four arguments or a single tuple of four arguments:
def create_point(*args):
if len(args) == 1:
timestamp, metric_name, values, tags = args[0]
elif len(args) == 4:
timestamp, metric_name, values, tags = args
else:
raise TypeError('too many or too few arguments')
...
But your current solution seems good to me. The create_point function is
self-documenting with four named arguments. You can pass the items
directly:
pt = create_point(this, that, other, another)
or by unpacking a sequence:
pt = create_point(*fourvalues)
Whatever you do, *something* has to unpack the four values. So why not do it
when you call the function?
There is one last possibility. I hesitate to mention it, because it is for
Python 2 only and is not supported in Python 3, but you can also do this:
# Python 2 only
def create_point((timestamp, metric_name, values, tags)):
...
Notice the extra pair of parens? This means that create_point now takes a
single argument, which is automatically unpacked into the four names given.
It is equivalent to the following version:
# Python 3 or Python 2
def create_point(items):
timestamp, metric_name, values, tags = items
...
which I already showed.
> I am calling get_metric in a for loop like so:
>
> for metric_data in get_metrics(server_status_json, mmapv1_metrics,
> line_number):
> json_points.append(create_point(*metric_data))
This version looks fine to me. You're going to have to unpack the data
somewhere, this is as good as place as any other. Or you could write this:
# use nicer names, of course
for a, b, c, d in get_metrics(
server_status_json, mmapv1_metrics, line_number):
json_points.append(create_point(a, b, c, d))
It's all much the same whichever way you do it. I doubt there is any
efficiency difference, pick the version you like to read the most.
> I was hoping to use tuple unpacking to pass metric_data straight from
> get_metrics through to create_point.
>
> However, in this case, metric_data only contains timestamp.
I don't understand this.
--
Steven
More information about the Python-list
mailing list