Chaining function calls in main. Is it "Pythonic"?

Viewed 170

Lately, some of my code has led me to a question about using outputs of functions as variables, then to use those same variables as parameters in other functions. All when defining main. I believe this can lead to errors when debugging and confusion when using a file as a module.

An example is below:

def add_two_numbers(x, y):
    z = x + y
    return z

def now_divide_two(z, s):
    t = z / s 
    return t

First method:

def main():
    added = add_two_numbers(5, 10)
    final_output = now_divide_two(added, 3)
    print(final_output)

Second method:

def main():
    final_output = now_divide_two(add_two_numbers(5,10), 3)
    print(final_output)

Style guides and good practice suggest the first method is superior to the second. Yet, I still feel that they are both "unpythonic". With that, let's assume functions become more complicated, but still require the principle of using each others outputs as the next one's parameters. What is the recommended methodology for running functions in main?

3 Answers

There's nothing unpythonic about passing the results of a function to another function. It's often the best way of doing things.

The first style is better than the second style in terms of clarity because it's a lot easier to tell what the value being passed to now_divide_two represents. In the second method, you aren't declaring the variable to be passed to now_divide_two, so you have to guess what the value you're passing represents. In the first method, there is a variable with a name, so you know reasonably well what the variable means and why you are passing it to another function.

Sometimes, however, it's easy to assume what the arguments to functions mean (like str for example), and in those cases it can be better to just pass the results of the function directly to the other function.

Functionally, both approaches are equivalent (barring minor differences such as temporary vs explicitly named variables), so neither is inherently "better" than the other.

"Better" is a matter of practical needs and circumstances. Some concrete considerations to help you decide in the cases you may encounter:

  • The one line approach uses fewer lines of code. This is sometimes (very seldom) important.
  • Using a temporary variable instead of a new namespace entry may, in some cases provide a very marginal performance boost. This is again neither a likely nor worthwhile optimization to pursue in most situations.
  • If you want to log or otherwise process the intermediate values, you will have to use the multiline approach.
  • Having more shorter lines is generally more readable. Readability is more useful than brevity, especially with a language like Python.

As you can tell, I personally tend to lean towards having intermediate assignments rather than monolithic one liners. However, that's usually a matter of taste. When possible, weigh the pros and cons of different approaches. Sometimes you have to recognize that it really doesn't matter, and just go with what seems nicer to you in the moment.

First method is imperative. Second is functional. Many people outside of academic contexts tend to use imperative style, citing readability as the reason. If you prefer the second style you may like Lisp or Clojure, where functional programming is dominant

Related