A function is a piece of code that accomplishes a specific task. It usually takes in argument(s) as input, does some processing, and returns a result. Once a function is written, it can be called over and over again.
Functions take advantage of abstraction: we don't care how the function carries out its task, we just care that it gives us a correct result.
In addition, functions allow us to reuse code instead of rewriting it to work with different values.
A pure function produces no effects other than returning a value. Its return value depends only on the inputs. Given the same arguments, it always returns the same value.
addalways returns the sum of the arguments and has no side effects.
A non-pure function or impure function produces a side effect (e.g., mutation, printing to screen). Its return value may depend on external state.
Functions that modify a variable in another frame
get_a() function modifies the variable
a in the global frame:
a = 0 def get_a(): global a a += 1 return a - 1
tick function modifies the variable
n in the
def countdown(n): def tick(): nonlocal n n -= 1 return n return tick
Functions that mutate an object in another frame
add_square function mutates
lst in the global frame:
lst =  def append_square(n): lst.append(n*n)