Variables are one of the two fundamental components of any programming language. Now that we know what variables are (they things that store data) and how to work with them, we can introduce the the other fundamental component of programming: functions.

Functions give us the ability to write some code that we reference over and over again without having to retype things. Ultimately, programming is about making your life easier! We work hard (say, for one semester of our lives) learning how to give a computer instructions (using Python) and then, for the rest of our lives, everything else is easier and more convenient because we can instruct a computer to do lots of the heavy lifting for us. In financial terms, we spend a little time now for a bunch of time saved later, and thus the net present value of learning to program is positive.

Functions have three parts:

  1. Function defintion (name the function and determine what inputs we need, if any)

  2. Operations (execute some code)

  3. Return statement (define what want we want to get back from the function)

As an example, let’s compute the weighted average cost of capital, defined as

\[ r_{\text{WACC}} = \frac{E}{V}\times r_E + \frac{D}{V}\times r_D\times (1-\tau_C). \]

That is, the weighted average cost of capital for a firm is the proportion of equity in the firm times the equity cost of capital plus the proportion of debt in the firm times the debt cost of capital. We adjust the latter for the tax shield of debt using the corporate tax rate \(\tau_C\).

Part 1: definition

A function defintion begins with the keyword def followed by the function name and then a colon.

Functions can use information passed to it via input arguments (inputs are named in the parentheses, which appear before the colon).

def wacc(E, D, rE, rD, tC):

Note that in this function definition, we expect E and D as inputs. We do not require V to be an input to the function, since V is easily calculated as V = E + D. This calculation is included in part 2.

Part 2: operations

Functions run the code written inside of the function (operations) when the function is called. A function call occurs when a programmer ‘’uses’’ the function, and we’ll see an example of this shortly.

NOTE: indentation keeps track of whether code is ‘’inside’’ a function

def wacc(E, D, rE, rD, tC):
    V = E + D
    cost_of_capital = E / V * rE + D / V * rD * (1 - tC)

Part 3: return value

Functions can be many, many lines of code.

The last line, starting with the keyword return specifies what value comes back when you run the function.

def wacc(E, D, rE, rD, tC):
    V = E + D
    cost_of_capital = E / V * rE + D / V * rD * (1 - tC)
    return cost_of_capital

When a function is created, Python becomes ‘’aware’’ of the function, but nothing else happens at that time.

def wacc(E, D, rE, rD, tC):
    V = E + D
    cost_of_capital = E / V * rE + D / V * rD * (1-tC)
    return cost_of_capital

For functions to be used, they need to be called. For example:


tells Python to compute the weighted average cost of capital for a firm with an equity value of \(100\), a debt value of \(30\), an equity cost of capital of \(8\%\), a debt cost of capital of \(4\%\), and a tax rate of \(35\%\). The returned value of 0.0675 tells us that the firm’s WACC is \(6.75\%\).

In the above example, Python assumes the first number (\(100\)) should be given to the input variable E, it assumes that the second number (\(30\)) should be given to the input variable D, etc. This is bad practice! It’s much better to use the input variable names:


because then the ordering of how you enter the inputs doesn’t matter.


This is useful to keep in mind because, realistically, you won’t remember the default ordering of inputs (the order of input variables in the def line of the function definition).

The return line is important because variables that live inside a function are stuck inside that function.

E.g. the below will throw an error because cost_of_capital is only accessible inside the function wacc.

NameError                                 Traceback (most recent call last)
<ipython-input-5-967605eceae6> in <module>
----> 1 cost_of_capital

NameError: name 'cost_of_capital' is not defined

In order to get the value cost_of_capital back from the function, we specify that this value should be returned from the function. If desired, we can instruct the function to return multiple items to us. For instance, the wacc() function defined above returns only the cost of capital. If we want to return the total firm value, V, along with the cost of capital, we can easily modify the function to do so.

def more_wacc(E, D, rE, rD, tC):
    V = E + D
    cost_of_capital = E / V * rE + D / V * rD * (1-tC)
    return cost_of_capital, V
(0.06753846153846155, 130)

By default, Python is printing out the returned item(s) from the function. This happens because, if Python is not told to save the returned item(s) anywhere, Python simply prints it out. We can instead save the returned item(s) to a variable.

r_W = wacc(E=100,D=30,rE=.08,rD=.04,tC=.35)

This will preserve the returned item for later use. For instance, suppose that we calculate the cost of capital and then estimate the present value of a series of three dividend payments (one today, one in a year from now, and one in two years from now). For simplicity, let’s assume each divident payment is $5.

5 + 5/(1+r_W) + 5/(1+r_W)**2

If multiple items are returned from a function and we save the returned items to a variable, that variable will be a list.

x = more_wacc(E=100,D=30,rE=.08,rD=.04,tC=.35)
(0.06753846153846155, 130)

Concept check: Use the more_wacc() function to calculate WACC under the following parameter values:

  • E=200

  • D=80

  • rE=.09

  • rD=0.8

  • tC=.4