%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Tutorial slides on Python. % % Author: Prabhu Ramachandran % Copyright (c) 2005-2009, Prabhu Ramachandran %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \documentclass[compress,14pt]{beamer} % \documentclass[handout]{beamer} % \usepackage{pgfpages} % \pgfpagesuselayout{4 on 1}[a4paper,border, shrink=5mm,landscape] \usepackage{tikz} \newcommand{\hyperlinkmovie}{} %\usepackage{movie15} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Note that in presentation mode % \paperwidth 364.19536pt % \paperheight 273.14662pt % h/w = 0.888 \mode { \usetheme{Warsaw} %\usetheme{Boadilla} %\usetheme{default} \useoutertheme{infolines} \setbeamercovered{transparent} } % To remove navigation symbols \setbeamertemplate{navigation symbols}{} \usepackage{amsmath} \usepackage[english]{babel} \usepackage[latin1]{inputenc} \usepackage{times} \usepackage[T1]{fontenc} % Taken from Fernando's slides. \usepackage{ae,aecompl} \usepackage{mathpazo,courier,euler} \usepackage[scaled=.95]{helvet} \usepackage{pgf} \definecolor{darkgreen}{rgb}{0,0.5,0} \usepackage{listings} \lstset{language=Python, basicstyle=\ttfamily\bfseries, commentstyle=\color{red}\itshape, stringstyle=\color{darkgreen}, showstringspaces=false, keywordstyle=\color{blue}\bfseries} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % My Macros \setbeamercolor{postit}{bg=yellow,fg=black} \setbeamercolor{emphbar}{bg=blue!20, fg=black} \newcommand{\emphbar}[1] {\begin{beamercolorbox}[rounded=true]{emphbar} {#1} \end{beamercolorbox} } %{\centerline{\fcolorbox{gray!50} {blue!10}{ %\begin{minipage}{0.9\linewidth} % {#1} %\end{minipage} % }}} \newcommand{\myemph}[1]{\structure{\emph{#1}}} \newcommand{\PythonCode}[1]{\lstinline{#1}} \newcommand{\tvtk}{\texttt{tvtk}} \newcommand{\mlab}{\texttt{mlab}} \newcommand{\typ}[1]{\lstinline{#1}} \newcounter{time} \setcounter{time}{0} \newcommand{\inctime}[1]{\addtocounter{time}{#1}{\vspace*{0.1in}\tiny \thetime\ m}} \newcommand\BackgroundPicture[1]{% \setbeamertemplate{background}{% \parbox[c][\paperheight]{\paperwidth}{% \vfill \hfill \hfill \vfill }}} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Configuring the theme %\setbeamercolor{normal text}{fg=white} %\setbeamercolor{background canvas}{bg=black} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Title page \title[Python Development]{Python Development} \author[FOSSEE] {FOSSEE} \institute[IIT Bombay] {Department of Aerospace Engineering\\IIT Bombay} \date[] {8 November, 2009\\Day 2, Session 4} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %\pgfdeclareimage[height=0.75cm]{iitblogo}{iitblogo} %\logo{\pgfuseimage{iitblogo}} \AtBeginSection[] { \begin{frame} \frametitle{Outline} \Large \tableofcontents[currentsection,currentsubsection] \end{frame} } %% Delete this, if you do not want the table of contents to pop up at %% the beginning of each subsection: \AtBeginSubsection[] { \begin{frame} \frametitle{Outline} \tableofcontents[currentsection,currentsubsection] \end{frame} } \AtBeginSection[] { \begin{frame} \frametitle{Outline} \tableofcontents[currentsection,currentsubsection] \end{frame} } %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % DOCUMENT STARTS \begin{document} \begin{frame} \maketitle \end{frame} \section{Tests: Getting started} \begin{frame}[fragile] \frametitle{gcd revisited!} \begin{itemize} \item Open gcd.py \end{itemize} \begin{lstlisting} def gcd(a, b): if a % b == 0: return b return gcd(b, a%b) print gcd(15, 65) print gcd(16, 76) \end{lstlisting} \begin{itemize} \item python gcd.py \end{itemize} \end{frame} \begin{frame}[fragile] \frametitle{Find lcm using our gcd module} \begin{itemize} \item Open lcm.py \item $lcm = \frac{a*b}{gcd(a,b)}$ \end{itemize} \begin{lstlisting} from gcd import gcd def lcm(a, b): return (a * b) / gcd(a, b) print lcm(14, 56) \end{lstlisting} \begin{itemize} \item python lcm.py \end{itemize} \begin{lstlisting} 5 4 56 \end{lstlisting} \end{frame} \begin{frame}[fragile] \frametitle{Writing stand-alone module} Edit gcd.py file to: \begin{lstlisting} def gcd(a, b): if a % b == 0: return b return gcd(b, a%b) if __name__ == "__main__": print gcd(15, 65) print gcd(16, 76) \end{lstlisting} \begin{itemize} \item python gcd.py \item python lcm.py \end{itemize} \end{frame} \begin{frame}[fragile] \frametitle{More use of main} For automating tests. \begin{lstlisting} if __name__ == '__main__': for line in open('numbers.txt'): numbers = line.split() x = int(numbers[0]) y = int(numbers[1]) result = (int(numbers[2])) assert gcd(x, y) == result \end{lstlisting} \end{frame} \section{Coding Style} \begin{frame}{Readability and Consistency} \begin{itemize} \item Readability Counts!\\Code is read more often than its written. \item Consistency! \item Know when to be inconsistent. \end{itemize} \end{frame} \begin{frame}[fragile] \frametitle{A question of good style} \begin{lstlisting} amount = 12.68 denom = 0.05 nCoins = round(amount/denom) rAmount = nCoins * denom \end{lstlisting} \pause \begin{block}{Style Rule \#1} Naming is 80\% of programming \end{block} \end{frame} \begin{frame}[fragile] \frametitle{Code Layout} \begin{itemize} \item Indentation \item Tabs or Spaces?? \item Maximum Line Length \item Blank Lines \item Encodings \end{itemize} \end{frame} \begin{frame}{Whitespaces in Expressions} \begin{itemize} \item When to use extraneous whitespaces?? \item When to avoid extra whitespaces?? \item Use one statement per line \end{itemize} \end{frame} \begin{frame}{Comments} \begin{itemize} \item No comments better than contradicting comments \item Block comments \item Inline comments \end{itemize} \end{frame} \begin{frame}{Docstrings} \begin{itemize} \item When to write docstrings? \item Ending the docstrings \item One liner docstrings \end{itemize} More information at PEP8: http://www.python.org/dev/peps/pep-0008/ \inctime{5} \end{frame} \section{Debugging} \subsection{Errors and Exceptions} \begin{frame}[fragile] \frametitle{Errors} \begin{lstlisting} In []: while True print 'Hello world' \end{lstlisting} \pause \begin{lstlisting} File "", line 1, in ? while True print 'Hello world' ^ SyntaxError: invalid syntax \end{lstlisting} \end{frame} \begin{frame}[fragile] \frametitle{Exceptions} \begin{lstlisting} In []: print spam \end{lstlisting} \pause \begin{lstlisting} Traceback (most recent call last): File "", line 1, in NameError: name 'spam' is not defined \end{lstlisting} \end{frame} \begin{frame}[fragile] \frametitle{Exceptions} \begin{lstlisting} In []: 1 / 0 \end{lstlisting} \pause \begin{lstlisting} Traceback (most recent call last): File "", line 1, in ZeroDivisionError: integer division or modulo by zero \end{lstlisting} \end{frame} \begin{frame}[fragile] \frametitle{Handling Exceptions} Python uses \typ{try} and \typ{except} clause. %%Revisiting the raw\_input \begin{lstlisting} a = raw_input('Enter number(Q to quit):') try: num = int(a) print num except: if a == 'Q': print 'Exiting...' else: print 'Wrong input!' \end{lstlisting} \end{frame} %% \begin{frame}[fragile] %% \frametitle{Solving it with \typ{try} and \typ{except}} %% \vspace{-0.2in} %% \begin{lstlisting} %% highest = 0 %% for record in open('sslc1.txt'): %% fields = record.split(';') %% try: %% total = 0 %% for score_str in fields[3:8]: %% score = int(score_str) %% total += score %% if total > highest: %% highest = total %% except: %% pass %% print highest %% \end{lstlisting} %% \end{frame} \subsection{Strategy} \begin{frame}[fragile] \frametitle{Debugging effectively} \begin{itemize} \item \typ{print} based strategy \item Process: \end{itemize} \begin{center} \pgfimage[interpolate=true,width=5cm,height=5cm]{DebugginDiagram.png} \end{center} \end{frame} \begin{frame}[fragile] \frametitle{Debugging effectively} \begin{itemize} \item Using \typ{\%debug} in IPython \end{itemize} \end{frame} \begin{frame}[fragile] \frametitle{Debugging in IPython} \small \begin{lstlisting} In []: import mymodule In []: mymodule.test() --------------------------------------------- NameError Traceback (most recent call last) in () mymodule.py in test() 1 def test(): ----> 2 print spam NameError: global name 'spam' is not defined In []: %debug > mymodule.py(2)test() 0 print spam ipdb> \end{lstlisting} \inctime{15} \end{frame} \subsection{Exercise} \begin{frame}[fragile] \frametitle{Debugging: Exercise} \small \begin{lstlisting} science = {} for record in open('sslc1.txt'): fields = record.split(';') region_code = fields[0].strip() score_str = fields[6].strip() score = int(score_str) if score_str != 'AA' else 0 if score > 90: science[region_code] += 1 pie(science.values(), labels=science.keys()) savefig('science.png') \end{lstlisting} \inctime{10} \end{frame} %% \begin{frame} %% \frametitle{Testing} %% \begin{itemize} %% \item Writing tests is really simple! %% \item Using nose. %% \item Example! %% \end{itemize} %% \end{frame} \section{Test Driven Approach} \begin{frame} \frametitle{Need for Testing!} \begin{itemize} \item Quality \item Regression \item Documentation \end{itemize} %% \vspace*{0.25in} %% \emphbar{It is to assure that section of code is working as it is supposed to work} \end{frame} \begin{frame}[fragile] \frametitle{Example} \begin{block}{Problem Statement} Write a function to check whether a given input string is a palindrome. \end{block} \end{frame} \begin{frame}[fragile] \frametitle{Function: palindrome.py} \begin{lstlisting} def is_palindrome(input_str): return input_str == input_str[::-1] \end{lstlisting} \end{frame} \begin{frame}[fragile] \frametitle{Test for the palindrome: palindrome.py} \begin{lstlisting} def test_function_normal_words(): input = "noon" assert is_palindrome(input) == True if __name__ == "main'': test_function_normal_words() \end{lstlisting} \end{frame} \begin{frame}[fragile] \frametitle{Running the tests.} \begin{lstlisting} $ nosetests palindrome.py . ---------------------------------------------- Ran 1 test in 0.001s OK \end{lstlisting} \end{frame} \begin{frame}[fragile] \frametitle{Exercise: Including new tests.} \begin{lstlisting} def test_function_ignore_cases_words(): input = "Noon" assert is_palindrome(input) == True \end{lstlisting} \vspace*{0.25in} Check\\ \PythonCode{$ nosetests palindrome.py} \\ \begin{block}{Task} Tweak the code to pass this test. \end{block} \end{frame} %\begin{frame}[fragile] % \frametitle{Lets write some test!} %\begin{lstlisting} %#for form of equation y=mx+c %#given m and c for two equation, %#finding the intersection point. %def intersect(m1,c1,m2,c2): % x = (c2-c1)/(m1-m2) % y = m1*x+c1 % return (x,y) %\end{lstlisting} % %Create a simple test for this % %function which will make it fail. % %\inctime{15} %\end{frame} % %% \begin{frame}[fragile] %% \frametitle{Exercise} %% Based on Euclid's algorithm: %% \begin{center} %% $gcd(a,b)=gcd(b,b\%a)$ %% \end{center} %% gcd function can be written as: %% \begin{lstlisting} %% def gcd(a, b): %% if a%b == 0: return b %% return gcd(b, a%b) %% \end{lstlisting} %% \vspace*{-0.15in} %% \begin{block}{Task} %% \begin{itemize} %% \item Write at least %% two tests for above mentioned function. %% \item Write a non recursive implementation %% of gcd(), and test it using already %% written tests. %% \end{itemize} %% \end{block} %% \inctime{15} %% \end{frame} \begin{frame} \frametitle{Summary} We have coverd: \begin{itemize} \item Following and Resolving Error Messages. \item Exceptions. \item Handling exceptions \item Approach for Debugging. \item Writting and running tests. \end{itemize} \end{frame} \end{document}