\section{Functions}

\begin{frame}[fragile]
  \frametitle{Abstracting}
  \begin{itemize}
  \item Reduce duplication of code
  \item Fewer lines of code and hence lesser scope for bugs
  \item Re-usability of code, that's already been written
  \item Use functions written by others, without exactly knowing how
    they do, what they are doing
  \item \alert{Enter Functions!}
  \end{itemize}
\end{frame}


\begin{frame}[fragile]
  \frametitle{Defining functions}
  \begin{itemize}
  \item Consider the function \texttt{f(x) = x\textasciicircum{}2}
  \item Let's write a Python function, equivalent to this
  \end{itemize}
  \begin{lstlisting}
   In[]: def f(x):
   ....:     return x*x
   ....:

   In[]: f(1)
   In[]: f(2)
  \end{lstlisting}
  \begin{itemize}
  \item \texttt{def} is a keyword  
  \item \texttt{f} is the name of the function 
  \item \texttt{x} the parameter of the function
  \item \texttt{return} is a keyword; specifies what should be
    returned
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Defining functions \ldots}
  \begin{lstlisting}
  In[]:  def greet():
  ....:      print "Hello World!"
  ....:

  In[]:  greet()
  \end{lstlisting}
  \begin{itemize}
  \item \texttt{greet} is a function that takes no arguments
  \item Also, it is not returning anything explicitly
  \item But implicitly, Python returns \texttt{None}
  \end{itemize}
  \begin{lstlisting}
  In[]:  def avg(a, b):
  ....:      return (a + b)/2
  ....:
      
  In[]:  avg(12, 10)
  \end{lstlisting}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Doc-strings}
  \begin{itemize}
  \item It's highly recommended that all functions have documentation
  \item We write a doc-string along with the function definition
  \end{itemize}
  \begin{lstlisting}
  In[]:  def avg(a, b):
         """ avg takes two numbers as input 
         and returns their average"""

  ....:      return (a + b)/2
  ....:
        
  In[]:  avg?
  In[]:  greet?
  \end{lstlisting}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Returning multiple values}
  \begin{itemize}
  \item Return area and perimeter of circle, given radius
  \item Function needs to return two values
  \end{itemize}
  \begin{lstlisting}
  In[]:  def circle(r):
         """returns area and perimeter of a 
         circle given, the radius r"""

  ....:      pi = 3.14
  ....:      area = pi * r * r
  ....:      perimeter = 2 * pi * r
  ....:      return area, perimeter
  ....:

  In[]:  circle(4)
  In[]:  a, p = circle(6)
  In[]:  print a
  In[]:  print p
  \end{lstlisting}
  \begin{itemize}
  \item Any number of values can be returned
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
  \frametitle{What? -- 1}
  \begin{lstlisting}       
  In[]:  def what( n ):           
  ....:      if n < 0: n = -n     
  ....:      while n > 0:         
  ....:          if n % 2 == 1:   
  ....:              return False 
  ....:          n /= 10          
  ....:      return True          
  ....:
  \end{lstlisting}         
\end{frame}

\begin{frame}[fragile]
  \frametitle{What? -- 2}
  \begin{lstlisting}
  In[]:  def what( n ):
  ....:      i = 1
  ....:      while i * i < n:
  ....:          i += 1
  ....:      return i * i == n, i
  ....:
  \end{lstlisting}
\end{frame}

\subsection*{Default \& Keyword Arguments}

\begin{frame}[fragile]
  \frametitle{Default arguments}
  \begin{lstlisting}
  In[]: round(2.484)
  In[]: round(2.484, 2)

  In[]:  s.split() # split on spaces
  In[]:  s.split(';') # split on ';'

  In[]: range(10) # returns numbers from 0 to 9
  In[]: range(1, 10) # returns numbers from 1 to 9
  In[]: range(1, 10, 2) # returns odd numbers from 1 to 9
  \end{lstlisting}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Default arguments \ldots}
  \begin{lstlisting}
  In[]:  def welcome(greet, name="World"):
  ....:      print greet, name
  ....:

  In[]: welcome("Hi", "Guido")
  In[]: welcome("Hello")
  \end{lstlisting}
  \begin{itemize}
  \item Arguments with default values, should be placed at the end
  \item The following definition is \alert{WRONG}
  \end{itemize}
  \begin{lstlisting}
  In[]:  def welcome(name="World", greet):
  ....:      print greet, name
  ....:
  \end{lstlisting}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Keyword Arguments}
  \begin{lstlisting}
  In[]:  def welcome(greet, name="World"):
  ....:      print greet, name
  ....:

  In[]:  welcome("Hello", "James")

  In[]: welcome("Hi", name="Guido")

  In[]: welcome(name="Guido", greet="Hey")

  In[]:  welcome(name="Guido", "Hey")
  \end{lstlisting}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Built-in functions}
  \begin{itemize}
  \item Variety of built-in functions are available
  \item \texttt{abs, any, all, len, max, min}
  \item \texttt{pow, range, sum, type}
  \item Refer here:
    \url{http://docs.python.org/library/functions.html}
  \end{itemize}
\end{frame}

\subsection*{Variable Scope}

\begin{frame}[fragile]
  \frametitle{Arguments are local}
  \begin{lstlisting}
   In[]: def change(q):
   ....:     q = 10
   ....:     print q
   ....:

  In[]:  change(1)
  In[]:  print q
  \end{lstlisting}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Variables inside function are local}
  \begin{lstlisting}
  In[]:  n = 5
  In[]:  def change():
  ....:      n = 10
  ....:      print n
  ....:
  In[]:  change()
  In[]:  print n
  \end{lstlisting}
  \begin{itemize}
  \item Use the \texttt{global} statement to assign to global variables
  \end{itemize}
  \begin{lstlisting}
  In[]:  def change():
  ....:      global n
  ....:      n = 10
  ....:      print n
  ....:
  In[]:  change()
  In[]:  print n
  \end{lstlisting}
\end{frame}

\begin{frame}[fragile]
  \frametitle{global}
 \begin{itemize}
  \item Use the \texttt{global} statement to assign to global variables
  \end{itemize}
  \begin{lstlisting}
  In[]:  def change():
  ....:      global n
  ....:      n = 10
  ....:      print n
  ....:
  In[]:  change()
  In[]:  print n
  \end{lstlisting}
\end{frame}  

\begin{frame}[fragile]
  \frametitle{Mutable variables}
  \begin{itemize}
  \item Behavior is different when assigning to a list element/slice
  \item Python looks up for the name, from innermost scope outwards,
    until the name is found
  \end{itemize}
  \begin{lstlisting}
  In[]:  name = ['Mr.', 'Steve', 'Gosling']
  In[]:  def change_name():
  ....:      name[0] = 'Dr.'
  ....:
  In[]: change_name()
  In[]: print name
  \end{lstlisting}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Passing Arguments \ldots}
  \begin{lstlisting}
  In[]:  n = 5
  In[]:  def change(n):
  ....:      n = 10
  ....:      print "n = %s inside change " %n
  ....:
  In[]:  change(n)
  In[]:  print n
  \end{lstlisting}
  
  \begin{lstlisting}
  In[]:  name = ['Mr.', 'Steve', 'Gosling']
  In[]:  def change_name(n):
  ....:      n[0] = 'Dr.'
  ....:      print "n = %s inside change_name" %n
  ....:
  In[]:  change_name(name)
  In[]:  print name
  \end{lstlisting}
\end{frame}