%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Tutorial slides on Python.
%
% Author: FOSSEE
% Copyright (c) 2017, FOSSEE, IIT Bombay
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\documentclass[14pt,compress]{beamer}
\input{macros.tex}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Title page
\title[Functions]{Python language: Functions}

\author[FOSSEE Team] {The FOSSEE Group}

\institute[IIT Bombay] {Department of Aerospace Engineering\\IIT Bombay}
\date[] {Mumbai, India}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% DOCUMENT STARTS
\begin{document}

\begin{frame}
  \titlepage
\end{frame}

\section{Functions}

\begin{frame}[fragile]
  \frametitle{Functions for abstraction}
  \begin{itemize}
  \item Reduce duplication of code
  \item Fewer lines of code: lesser scope for bugs
  \item Re-usability of code
  \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 In Python:
  \end{itemize}
  \begin{lstlisting}
   In []: def f(x):
   .....:     return x*x
   .....:
   In []: f(1)
   In []: f(1+2j)
  \end{lstlisting}
  \begin{itemize}
  \item \typ{def} is a keyword
  \item \typ{f} is the name of the function
  \item \typ{x} the parameter of the function
  \item \typ{return} is a keyword
  \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 It returns nothing explicitly
  \item Implicitly, Python returns \typ{None}
  \item \typ{None} is also a built-in, immutable data type
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Defining functions \ldots}
  \begin{lstlisting}
  In []: def avg(a, b):
  .....:     return (a + b)/2
  .....:

  In []: avg(12, 10)
\end{lstlisting}
\begin{itemize}
\item \typ{avg} takes two arguments
\item Returns one value
\end{itemize}
\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}
def avg(a, b):
    """Returns the average of two
    given numbers."""
   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}
def circle(r):
    """Returns area and perimeter of
    circle given radius r"""
    pi = 3.14
    area = pi * r * r
    perimeter = 2 * pi * r
    return area, perimeter

In []: circle(4)
In []: a, p = circle(6)
  \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)
In []: range(1, 10)
In []: range(1, 10, 2)
  \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}
\end{frame}
\begin{frame}[fragile]
  \frametitle{Default arguments \ldots}
  \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,plain]
  \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}
Cannot have non-keyword args after kwargs
\end{frame}

\begin{frame}[fragile]
  \frametitle{Built-in functions}
  \begin{itemize}
  \item Variety of built-in functions are available
  \item \typ{abs, any, all, len, max, min}
  \item \typ{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}
\end{frame}

\begin{frame}[fragile]
  \frametitle{If not defined, look in parent scope}
  \begin{lstlisting}
  In []: n = 5
  In []: def scope():
  .....:     print(n)
  .....:
  In []: scope()
\end{lstlisting}
\begin{itemize}
\item Note that \typ{n} was not defined in \typ{scope}
\item It looked for the variable in previous scope
\item See: \url{pythontutor.com}
\end{itemize}
\end{frame}

\begin{frame}[fragile]
  \frametitle{\texttt{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, "inside change")
.....:
In []: change(n)
In []: print(n)
  \end{lstlisting}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Passing Arguments \ldots}
\begin{lstlisting}
In []: name = ['Mr.', 'Steve','Gosling']
In []: def change_name(x):
.....:     x[0] = 'Dr.'
.....:     print(x, 'in change')
.....:
In []: change_name(name)
In []: print(name)
  \end{lstlisting}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Passing Arguments \ldots}
\begin{lstlisting}
In []: name = ['Mr.', 'Steve','Gosling']
In []: def change_name(x):
.....:     x = [1,2,3]
.....:     print(x, 'in change')
.....:
In []: change_name(name)
In []: print(name)
  \end{lstlisting}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Passing Arguments \ldots}
\begin{lstlisting}
In []: name = ['Mr.', 'Steve','Gosling']
In []: def change_name(x):
.....:     x[:] = [1,2,3]
.....:     print(x, 'in change')
.....:
In []: change_name(name)
In []: print(name)
  \end{lstlisting}
\end{frame}


\subsection{Examples}

\begin{frame}[fragile]
  \frametitle{Functions: example}
  \begin{lstlisting}
def signum( r ):
    """returns 0 if r is zero
    -1 if r is negative
    +1 if r is positive"""
    if r < 0:
        return -1
    elif r > 0:
        return 1
    else:
        return 0
  \end{lstlisting}
  \emphbar{Note docstrings}
\end{frame}

\begin{frame}[fragile]
  \frametitle {What does this function do?}
  \begin{lstlisting}
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 does this function do?}
\begin{lstlisting}
def what(n):
    i = 1
    while i * i < n:
        i += 1
    return i * i == n, i
  \end{lstlisting}
\end{frame}

\begin{frame}[fragile]
  \frametitle {What does this function do?}
  \begin{lstlisting}
def what(x, n):
    if n < 0:
       n = -n
       x = 1.0 / x

    z = 1.0
    while n > 0:
        if n % 2 == 1:
            z *= x
        x *= x
        n //= 2
    return z
  \end{lstlisting}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Nested functions}
  \begin{lstlisting}
    def f(x):
        def g(x):
            return x+1
        return g(x)**2
  \end{lstlisting}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Nested functions: returning functions}
  \begin{lstlisting}
    def f():
        def g(x):
            return x+1
        return g

    In []: func = f()
    In []: func(1)
    In []: f()(1)  # Also valid!
  \end{lstlisting}
\end{frame}


\begin{frame}
  \frametitle{Summary}
  \begin{itemize}
  \item Defining functions
  \item Taking either 0, or more arguments
  \item Returning \typ{None} implicitly or any number of values
  \item Default and keyword arguments
  \item Variable scope, \typ{global}
  \item Mutable and immutable arguments
  \item Nested functions
  \end{itemize}
\end{frame}

\end{document}