Yes, but with most functions there's no choice, because most of the functions in your program do something (a) complex and/or (b) specific to your program. This `get_single` function falls into neither of these categories.
It is certainly okay for some functions to be complex. Some may rely on simpler functions, but the one you'd use can still do a complex task in general.
A function that squares a number is simple, one that computes the standard deviation is definitely more complex.
> A function that squares a number is simple, one that computes the standard deviation is definitely more complex.
I'm talking about the complexity difference between this:
def stddev(pop):
total = 0
count = 0
for x in pop:
total += x
count += 1
mean = total / float(count)
variance = 0
for x in pop:
variance += (x - mean)**2
return math.sqrt(variance)
and this:
def stddev(pop):
return math.sqrt(variance(pop))
def variance(pop):
m = mean(pop)
return sum(square(x - m) for x in pop)
def mean(pop):
return sum(pop) / float(len(pop))
def square(x):
return x**2
The first is a (mildly) complex function. The latter are all simple functions, and the complex result is constructed by composing simple operations.
Good programmers write functions in the latter style, not the former.
Good programmers write functions in the latter style, not the former.
Well, that stddev function could be much less verbose:
def stddev(pop):
mean = sum(pop) / float(len(pop))
variance = sum( (x-mean)**2 for x in pop)
return math.sqrt(variance)
To me that's easier to read than jumping back and forth between multiple function definitions. Of course, if you need the mean or variance independently then your way is better.
> Well, that stddev function could be much less verbose:
Sure, it could, but I was demonstrating what it looked like without the use of functions. Your example proves my point just as mine does: sum(), like mean() or variance() in my example, is just a simple function, the kind that I'm arguing for. The fact that it's built into Python (rather recently, I note) doesn't change that fact or reduce the impact of the argument. Your example simply goes one step down the path, and mine goes further.
> To me that's easier to read than jumping back and forth between multiple function definitions.
You don't have to jump back and forth between function definitions. Let's say you don't know what the standard deviation is, but you know what the mean is. You can look at the definition of stddev() and see, "Ah, it's clearly the sqrt() of the variance. What's the variance? Ah, it's the sum of the squares of difference between each element and the mean." You know what the mean() does (its name is pretty clear) and you know what sum() and square() do, so you never have to look at those functions. Someone else who knows what the variance is would never have to look that deep. When someone is reading the stddev() in my example, he doesn't have concern himself with implementation details of functions he already understands. When someone is reading yours, he has to at least read how the mean is calculated. He can't avoid it--it's right there.
> Of course, if you need the mean or variance independently then your way is better.
You almost certainly will in any case where you're using the standard deviation, but that's just an artifact of the example. Other advantages of using small, simple functions like in my example:
* More reusable (as you noted)
* More easily testable.
* More easily comprehensible (as I showed above)
* More easily documented (especially in a language like Python with its docstring support)
* More conceptual abstraction
Also, the performance here is probably much worse. (Although in many cases it would not matter.)
But that's just my opinion, your suggestion is legitimate.