\documentclass[14pt,compress,aspectratio=169]{beamer}

\input{macros.tex}

\title[Introduction to OOP]{Advanced Python}
\subtitle{Introduction to Object Oriented Programming }

\author[FOSSEE] {The FOSSEE Group}

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

\begin{document}

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

\begin{frame}
  \frametitle{Background and caveats}
  \begin{itemize}
  \item You don't need OOP for everything!
  \item Helps with larger programs
  \item Appreciate it, when you write more code
  \item Very useful to organize/modularize your code
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
  \frametitle{What are the benefits?}
  \begin{itemize}
  \item Create new data types
  \item Create objects to simulate a real problem
  \item Makes problem solving more natural and elegant
  \item Can be easier to understand
  \item Allows for code-reuse
  \end{itemize}
\end{frame}


\begin{frame}[fragile]
  \frametitle{Example: Managing Talks}
  \begin{itemize}
  \item Want to manage list of talks at a conference
  \end{itemize}
  \begin{lstlisting}
talk = {'Speaker': 'Guido van Rossum',
        'Title': 'The History of Python'
        'Tags': 'python,history,C,advanced'}

def get_first_name(talk):
    return talk['Speaker'].split()[0]

def get_tags(talk):
    return talk['Tags'].split(',')
  \end{lstlisting}
\end{frame}

\begin{frame}
  \frametitle{Issues}
  \begin{itemize}
  \item Not convenient to handle large number of talks
  \item Data separate from functions to manipulate talk
  \item Must pass \lstinline{talk} to each function
  \item No clear organization
  \item What if we had different kinds of talks?
  \end{itemize}
\end{frame}


\begin{frame}[fragile]
  \frametitle{Creating a \typ{class}}
  \begin{lstlisting}
class Talk:
    """A class for the Talks."""
    def __init__(self, speaker, title, tags):
        self.speaker = speaker
        self.title = title
        self.tags = tags
  \end{lstlisting}
  \begin{itemize}
  \item \lstinline{class} is a keyword
  \item \lstinline{Talk} is the name of the class
  \item Notice the class doc-string
  \item Notice the indentation
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
  \frametitle{methods and \lstinline{self}}
  \begin{lstlisting}
class Talk:
    # ...
    def get_speaker_firstname(self):
        return self.speaker.split()[0]

    def get_tags(self):
        return self.tags.split(',')
  \end{lstlisting}
  \begin{itemize}
  \item \lstinline{self} is a reference to the object itself
  \item The name \lstinline{self} is a convention
  \item Instance variables: \lstinline{self.name}
  \end{itemize}
\end{frame}

\begin{frame}[fragile, plain]
  \frametitle{Exercise: type this out}
  \vspace*{-0.1in}
  \begin{lstlisting}
class Talk:
    """A class for the Talks."""
    def __init__(self, speaker, title, tags):
        self.speaker = speaker
        self.title = title
        self.tags = tags

    def get_speaker_firstname(self):
        return self.speaker.split()[0]

    def get_tags(self):
        return self.tags.split(',')
  \end{lstlisting}
\end{frame}


\begin{frame}[fragile]
  \frametitle{Instantiating a class to create objects}
  \begin{itemize}
  \item Creating objects or instances of a class is simple
  \item Call class, with arguments required by \lstinline{__init__}
  \end{itemize}
  \begin{lstlisting}
In []: bdfl = Talk('Guido van Rossum',
  ...:             'The History of Python',
  ...:             'python,history,C,advanced')
  \end{lstlisting}
  \begin{itemize}
  \item We can now call the methods of the Class
  \end{itemize}
  \begin{lstlisting}
In []: bdfl.get_tags()
In []: bdfl.get_speaker_firstname()
  \end{lstlisting}
\end{frame}

\begin{frame}[fragile]
  \frametitle{\lstinline{__init__} method}
  \begin{itemize}
  \item A special method
  \item Called every time an instance of the class is created
  \end{itemize}
  \begin{lstlisting}
In []: print(bdfl.speaker)
In []: print(bdfl.tags)
In []: print(bdfl.title)
  \end{lstlisting}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Creating more instances}
  \begin{lstlisting}
In []: talk = Talk('Arun K',
  ...:      'Python in biosciences', 'python,bio')
In []: talk.get_tags()
In []: talk.tags

In []: type(talk)
Out[]: __main__.Talk
In []: type(bdfl)
\end{lstlisting}
\begin{itemize}
\item Note that \lstinline{talk} and \lstinline{bdfl} are different objects
\item Different values but same type
\item \lstinline{Talk} \alert{encapsulates} the data and behavior of a talk
\end{itemize}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Changing/adding attributes}
\begin{lstlisting}
In []: talk.speaker = 'Arun K P'

In []: talk.tags = 'python,bioscience'
\end{lstlisting}
\pause
\begin{lstlisting}
# Adding attributes

In []: talk.x = 1

In []: talk.y = 'hello'
\end{lstlisting}
\end{frame}

\begin{frame}
  \frametitle{Summary}
  \begin{itemize}
  \item Introduction to Object Oriented Programming
  \item A simple example
  \item Defining a \lstinline{class}
  \item Methods and attributes: encapsulation
  \item Changing/adding attributes
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Exercise: simplest class}
  \begin{block}{}
    Create the simplest possible class, called \lstinline{Simple}, which has
    no attributes or methods.  Try this out on your own IPython interpreters.
    You should be able to instantiate it as follows:
  \end{block}
\begin{lstlisting}
In []: s = Simple()
\end{lstlisting}
  \pause
  \begin{block}{Hint}
    Remember the \lstinline{pass} statement?
  \end{block}
\end{frame}


\begin{frame}[plain, fragile]
  \frametitle{Solution}
\begin{lstlisting}
class Simple:
    pass
\end{lstlisting}
  \vspace*{0.5in}

  That is all!
\end{frame}

\begin{frame}[fragile,plain, fragile]
  \frametitle{Exercise: \lstinline{Person} class 1}
  \begin{block}{}
    Create a simple \lstinline{Person} class with two attributes: a
    \lstinline{name} (a string) and an \lstinline{age} (a float).  To be used
    as follows:
  \end{block}
\begin{lstlisting}
In []: p = Person('Arun', 22.0)
\end{lstlisting}
\end{frame}


\begin{frame}[plain, fragile]
  \frametitle{Solution}
\begin{lstlisting}
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
\end{lstlisting}
\end{frame}

\begin{frame}[plain, fragile]
  \frametitle{Exercise: \lstinline{Person} class 2}
  \begin{block}{}
    Create a simple \lstinline{Person} class with two attributes a
    \lstinline{name} and an \lstinline{age}.  However, let the name default to
    the string \lstinline{'name'} and the age default to 0.0.
  \end{block}
\begin{lstlisting}
In []: p = Person()
In []: print(p.name, p.age)
name 0.0
\end{lstlisting}
\end{frame}

\begin{frame}[plain, fragile]
  \frametitle{Solution}
\begin{lstlisting}
class Person:
    def __init__(self, name='name', age=0.0):
        self.name = name
        self.age = age
\end{lstlisting}
\end{frame}

\begin{frame}[fragile,plain, fragile]
  \frametitle{Exercise: simple method}
  \begin{block}{}
    Create a simple \lstinline{Person} class with two attributes as before.
    Add a method called \lstinline{birthday} which takes no arguments and
    which prints \lstinline{'HBD <name>'} and also increases the age by 1.
    Note that \lstinline{<name>} is the name of the instance.
  \end{block}

\begin{lstlisting}
In []: p = Person(name='Ram')
In []: p.birthday()
HBD Ram
In []: p.age
Out[]: 1.0
\end{lstlisting}
\end{frame}

\begin{frame}[plain, fragile]
  \frametitle{Solution}
\begin{lstlisting}
class Person:
    def __init__(self, name='name', age=0.0):
        self.name = name
        self.age = age

    def birthday(self):
        print('HBD', self.name)
        self.age += 1.0
\end{lstlisting}
\end{frame}



\end{document}