Question

This question came from looking at this question:

def fringe8((px, py), (x1, y1, x2, y2)):

Personally, it's been one of my pet peeves to see a function that takes two arguments with fixed-number iterables (like a tuple) or two or more dictionaries (Like in the Shotgun API). It's just hard to use, because of all the verbosity and double-bracketed enclosures.

Wouldn't this be better:

>>> class Point(object):
...     def __init__(self, x, y):
...         self.x = x
...         self.y = y
...     
>>> class Rect(object):
...     def __init__(self, x1, y1, x2, y2):
...         self.x1 = x1
...         self.y1 = y1
...         self.x2 = x2
...         self.y2 = y2
...     
>>> def fringe8(point, rect):
...     # ...
...
>>>
>>> point = Point(2, 2)
>>> rect = Rect(1, 1, 3, 3)
>>>
>>> fringe8(point, rect)

Is there a situation where taking two or more iterable arguments is justified? Obviously the standard itertools Python library needs that, but I can't see it being pretty in maintainable, flexible code design.

Was it helpful?

Solution

The def syntax with unpacking, like

def fringe8((px, py), (x1, y1, x2, y2)):

is gone in Python 3 -- which means Guido considered it a design error, or at least an unwarranted complication. Named tuples might be even better than special-purpose classes for the clarifying purpose you suggest.

However, having functions that take multiple iterable arguments is just perfectly fine -- itertools obviously cannot encapsulate every multi-iterable manipulation your applications might need, of course! Thinking of an iterable as "a stream" (possibly an unbounded one), there are vast number of ways in which you might want to "merge" multiple streams into one, for example (e.g. think of streams that are known to be sorted and you might want to build the intersection of, or the union, with or without removal of duplicates, etc, etc).

Why ever should one contort one's API's design to obey a perfectly arbitrary injunction about having no more than one iterable per function signature?!

OTHER TIPS

I agree with you that people tend to over-use lists and dictionaries as data structures just because they can. They see it as a simple way to group like data that doesn't require any work to define a class or deal with constructors. However, when you start to do more tasks with this data, you find that it is hard to remenber which piece of data was 2nd on the list and which was 5th. Making a class allows things to be more clearly defined and lets you compartmentalize functions that work directly on your data structure.

While you are thinking about it as having multiple iterables, I don't see that as the problem here. Some functions really do require multiple lists (see the built-in zip). But I think the example you gave is a case where the tuples are being used because it seems easier, but may not be as clear.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top