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

\input{macros.tex}

\title[OOP containership]{Advanced Python}
\subtitle{Object Oriented Programming: containership }

\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{Recap}
  \begin{itemize}
  \item Created \lstinline{Talk} and \lstinline{Tutorial} classes
  \item Know how to create objects: instantiation of a class
    \vspace*{0.5in}

  \item Let us create a conference!
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Conference class}
  \vspace*{-0.1in}
\begin{lstlisting}
class Conference:
    def __init__(self, talks=None):
        if talks is None:
            talks = []
        self.talks = talks

    def add_talk(self, talk):
        self.talks.append(talk)

    def schedule(self):
        for talk in self.talks:
            print(talk.speaker, talk.title)
\end{lstlisting}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Using this}
\begin{lstlisting}
In []: c = Conference()

In []: t = Talk('Guido', 'Python4', 'py,core')

In []: c.add_talk(t)

In []: c.schedule()

\end{lstlisting}
  \begin{itemize}
  \item Easy to read
  \item Nicely split up
  \item Reflects the real world

  \end{itemize}
\end{frame}

\begin{frame}[fragile]
  \frametitle{But why not this?}
\begin{lstlisting}
class Conference:
    def __init__(self, talks=[]):
        self.talks = talks
\end{lstlisting}
  \begin{itemize}
  \item Easier
  \item Less code
  \item Let's try it!
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Gotcha!}
\begin{lstlisting}
In []: c1 = Conference()
In []: c1.add_talk(1)
In []: c1.talks

In []: c2 = Conference()
In []: c2.talks

\end{lstlisting}

  \begin{itemize}
  \item What is going on?
  \end{itemize}
\end{frame}

\begin{frame}
  \frametitle{Beware of mutable default arguments!}
  \begin{itemize}
  \item Default arguments are evaluated once
  \item When the method/function is defined
  \item So, if the object is mutable we have a problem
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Which is why we have this}
\begin{lstlisting}
class Conference:
    def __init__(self, talks=None):
        if talks is None:
            talks = []
        self.talks = talks
\end{lstlisting}
\end{frame}

\begin{frame}
  \frametitle{Containership}
  \begin{itemize}
  \item \lstinline{Conference} class manages all the talks
  \item It contains the talks and tutorials
  \item Allows us to build complexity by \alert{composition}
  \item Hierarchical organization
  \item Allows us to mirror the real objects in code
  \end{itemize}
\end{frame}

\begin{frame}
  \frametitle{Some more examples}
  \begin{itemize}
  \item OOP for a \lstinline{Company}
  \item OOP for a \lstinline{Bank}
  \item OOP for a \lstinline{School} or \lstinline{College}
  \item OOP for a cell phone, computer, ...
  \end{itemize}
\end{frame}

\begin{frame}
  \frametitle{Design guidelines}
  \begin{itemize}
  \item Important to make sense
  \item Should be easy to explain the relationships and responsibilities of
    each class
  \item Inheritance should ``read'' correctly and make sense
  \item No object should be too responsible
  \item Functionality should be suitably delegated
  \end{itemize}
\end{frame}

\begin{frame}
  \frametitle{Summary}
  \begin{itemize}
  \item Creating a more complex class
  \item Containing other objects
  \item Issue with mutable default arguments
  \item Important design guidelines
  \end{itemize}
\end{frame}

\begin{frame}[plain, fragile]
  \frametitle{Exercise: Create a Zoo}
  \begin{block}{}
    Create a \py{Zoo} class which allows someone to add any number of animals.
    This means it should work for \py{Animal, Mammal, Human} objects. It
    should have a single \py{greet} method which calls the greet method of all
    of the animals it has and prints that:
  \end{block}

\begin{lstlisting}
In []: b = Animal('crow')
In []: m = Mammal('dog', legs=4)
In []: h = Human('Abhinav')
In []: z = Zoo(b, m, h)
In []: z.greet()
crow says greet
dog says greet
Abhinav says hello
\end{lstlisting}
\end{frame}


\begin{frame}[plain, fragile]
  \frametitle{Solution}
\begin{lstlisting}
class Zoo:
    def __init__(self, *animals):
        self.animals = list(animals)

    def greet(self):
        for animal in self.animals:
            print(animal.greet())
\end{lstlisting}
\end{frame}

\begin{frame}
  \frametitle{Observations}
  \begin{itemize}
  \item Notice the abstraction of \py{Animal}
  \item The \py{Zoo} will work with any object that has the \py{greet} method
  \item That is, any \py{Animal}
  \end{itemize}
\end{frame}

\end{document}
