Python for PHP Developers
@ben_nuttall
Raspberry Pi Foundation
About me
● Education Developer Advocate for Raspberry Pi Foundation
– Developer & maintainer of www.raspberrypi.org
– Education – teacher training & learning resources
– Outreach – open source, education & programming conferences
● From Sheffield
● BSc Mathematics & Computing in Manchester (MMU)
● Lived in Cambridge since late 2013
● Interested in programming, open source, Linux
About Raspberry Pi
● Family of affordable single board computers
– ~£15 700MHz single core 256MB RAM
– ~£25 900MHz quad core 1GB RAM
● Designed for use in education
● Used in education, industry and by hobbyists
● We're a charity (UK charity 1129409)
● Founded and based in Cambridge
● Staff of < 20
● Raspberry Pi manufactured in Pencoed, Wales (not China)
● Sold 6 million units since 2012 launch
What this talk is not
PHP
● $a = 1;
● function foo() {
    return “bar”;
}
● T_PAAMAYIM_NEKUDOTAYIM
Python
● a = 1
● def foo():
    return “bar”
● ???
What this talk is also not
YOU ARE ALL IDIOTS YOU
SHOULD BE USING PYTHON NOT
PHP IT'S NOT EVEN A REAL
LANGUAGE IT'S SO
INCONSISTENT I DON'T EVEN
What this talk is
● Examples of Python
● What makes Python code Pythonic
● How to think like a Python programmer
● Python Idioms
● Practical Python – frameworks, libraries, infrastructure
About Python
● General purpose high-level programming language
● Created in 1991 by Guido van Rossum
● Cross-platform
● Implemented in C (alternatives: Java, Python, C#)
● Multi-paradigm (OO, Imperative, Functional, Procedural)
● Dynamic type
● Designed for readability
Python is for...
● Web programming (Django, Pyramid, Bottle, Flask...)
● GUI development (wxPython, tkInter, PyGtk, PyQt...)
● Scientific and Numeric (SciPy, NumPy, Pandas...)
● Software development (Buildbot, Trac, Roundup...)
● System Administration (Ansible, Salt, OpenStack...)
● Embedded computing (Raspberry Pi, MicroPython, BeagleBone...)
● Education (Raspberry Pi, Turtle, Robotics...)
Why Python?
● Professional and powerful modern language
● Focus on readability
● Strong community
● Good documentation
● Flexible
● Full stack
Python 2 or Python 3?
● Python 3 was released in 2008, its current version is 3.4
● Python 2 is considered legacy, its EOL is 2020
– No more major revisions (2.7.x – no 2.8)
– However, everyone still uses it
● Python 3 is the present and future of the language
● Python 3 contains some nice new features
– But apparently not different enough for people to bother to change
– What version of PHP are you currently using in production? My guess: 5.3
● Some libraries don't support Python 3 yet
● Examples in this presentation are for Python 3
Which version do I have?
● Linux (including Raspberry Pi):
– python is Python 2
– python3 is Python 3
– (except Arch Linux – rebels)
● Mac:
– Python 2 pre-installed, Python 3 available from python.org/downloads
● Windows:
– Download either or both from python.org/downloads
Hello world
print(“Hello world”)
Built-in Numerical Types
● Numbers:
– Integer
● Decimal
● Binary
● Octal
● Hex
– Float
– Complex
● 123
● 0b01111011
● 0o173
● 0x7b
– 123.0
– 123 + 123j
Strings
● Single quotes
● Double quotes
● Triple quotes
● s = 'hello'
● s = “Hello”
● s = “””
Hello world,
how are you?
“””
Built-in Data Structures
● List
● Tuple
● Dictionary
● Set
● [1, 2, 3]
● (1, 2, 3)
● {
    'a': 1,
    'b': 2,
    'c': 3,
}
● {1, 2, 3}
Keywords
● False
● None
● True
● and
● as
● assert
● break
● class
● continue
● def
● del
● elif
● else
● except
● finally
● for
● from
● global
● if
● import
● in
● is
● lambda
● nonlocal
● not
● or
● pass
● raise
● return
● try
● while
● with
● yield
Built-in functions
● abs
● all
● any
● ascii
● bin
● bool
● bytearray
● bytes
● callable
● chr
● classmethod
● compile
● complex
● delattr
● dict
● dir
● divmod
● enumerate
● eval
● exec
● filter
● float
● format
● frozenset
● getattr
● globals
● hasattr
● hash
● help
● hex
● id
● input
● int
● isinstance
● issubclass
● iter
● len
● list
● locals
● map
● max
● memoryview
● min
● next
● object
● oct
● open
● ord
● pow
● print
● property
● range
● repr
● reversed
● round
● set
● setattr
● slice
● sorted
● staticmethod
● str
● sum
● super
● tuple
● type
● vars
● zip
Import
● import time
● from time import sleep
● from picamera import 
PiCamera
● Import the whole time module,
namespaced as time
● Import only the sleep function
from time module
● Import only the PiCamera class
from the picamera module
Import
● from datetime import 
datetime, timedelta
● import numpy as np
● from numpy import *
● Import only the datetime and 
timedelta functions from the
datetime module
● Import the numpy module,
namespaced as np
● Import all objects from numpy
module, polluting the namespace
(don't do this)
Paradigms
● Procedural
● Functional
● Object Oriented
Procedural
● C
● Go
● Fortran
● Pascal
● BASIC
Loops
for i in range(10):
    print(“Hello world”)
i = 0
while i < 10:
    i += 1
    print(“Hello world”)
    
while True:
    print(“Hello world”)
Iterables & Enumeration
people = [“Alice”, “Bob”, “Charlie”]
for person in people:
    print(“Hello %s” % person)
for i, name in enumerate(people):
    print(“%i: %s” % (i, name))
Functions
def greeting():
    print(“Hello”)
greeting()
Functions
def greeting(name):
    print(“Hello %s” % name)
greeting(“Ben”)
Functions
def greeting(name=None):
    if name:
        print(“Hello %s” % name)
    else:
        print(“Hello”)
greeting()
greeting(“Ben”)
Functions – positional & named arguments
def birthday_greeting(name=None, age=None):
    if name and age:
        print(“Happy %ith birthday, %s” % (age, name))
    elif name:
        print(“Happy birthday, %s” % name)
    elif age:
        print(“Happy %ith birthday” % age)
    else:
        print(“Happy birthday”)
birthday_greeting()  # use default arguments
birthday_greeting(“Ben”)  # positional argument
birthday_greeting(name=”Ben”, age=26)  # named arguments
birthday_greeting(age=26, name=”Ben”)  # named arguments, reverse order
birthday_greeting(age=26) # named argument
Functions – keyword arguments
def foo(**kwargs):
    if 'name' in kwargs:
        print(“Hello %s” % name)
Functions – globals (read only)
pi = 3.14159265358979
def circumference(radius):
    return 2 * pi * radius
Functions – globals (read/write)
total = 0
def add_one():
    global total
    total += 1
Functions – return vs. yield
def get_square_numbers(n):
    squares = []
    for i in range(n):
        squares.append(i**2)
    return squares
>>> get_square_numbers(10)
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
Functions – return vs. yield
def get_square_numbers(n):
    for i in range(n):
        yield i**2
>>> square_numbers = get_square_numbers(10)
>>> square_numbers.next()
0
>>> square_numbers.next()
1
Functional
● Haskell
● ML
● Common Lisp
● Scheme
● Clojure
● Erlang
● F#
List comprehension
squares = []
for n in range(10):
    squares.append(n**2)
print(squares)
squares = [i**2 for i in range(10)]
Set comprehension
>>> [i**2 for i in [­5, ­4, ­3, 2, 3, 4, 5]]
[25, 16, 9, 4, 9, 16, 25]
>>> {i**2 for i in [­5, ­4, ­3, 2, 3, 4, 5]}
{4, 9, 16, 25}
Dictionary comprehension
>>> {i: i**2 for i in range(5)}
{
 0: 0,
 1: 1,
 2: 4,
 3: 9,
 4: 16,
}
Generator Expressions
>>> squares = (i**2 for i in range(5))
>>> squares.next()
0
>>> squares.next()
1
Map
def square(n):
    return n**2
>>> things = [1, 2, 3]
>>> square_things = map(square, things)
>>> print(list(square_things))
[1, 4, 9]
functools & itertools
● functools - for higher-order functions: functions that act on or
return other functions
● itertools - a number of iterator building blocks inspired by
constructs from APL, Haskell, and SML, each recast in a form
suitable for Python
– product
– combinations
– permutations
Object Oriented
● C++
● Objective-C
● Smalltalk
● Java
● C#
● Ruby
Classes
class Dog:
    pass
>>> d = Dog()
Classes – init and properties
class Dog(object):
    def __init__(self, name):
        self.name = name
>>> d = Dog(“Bingo”)
>>> print(d.name)
Classes - methods
class Dog(object):
    def __init__(self, name):
        self.name = name
    def bark(self):
        print(“woof”)
>>> d = Dog(“Bingo”)
>>> d.bark()
woof
Classes - @property
class Dog(object):
    def __init__(self, name):
        self.name = name
        self.born = time()
    @property
    def age(self):
        return time() ­ self.born
>>> d = Dog(“Bingo”)
>>> print(d.age)
Classes – magic methods
class PlayingCard(object):
    VALUES = ('2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K', 'A')
    SUITS = ('H', 'D', 'S', 'C')
    def __init__(self, value, suit):
        self.value = value
        self.suit = suit
    def __repr__(self):
         return “%s%s” % (self.value, self.suit)
    def __eq__(self, other):
        return self.VALUES.index(self.value) == self.VALUES.index(other.value)
    def __lt__(self, other):
        return self.VALUES.index(self.value) < self.VALUES.index(other.value)
    def __gt__(self, other):
        return self.VALUES.index(self.value) > self.VALUES.index(other.value)
>>> card_1 = PlayingCard('A', 'S')
>>> card_2 = PlayingCard('9', 'D')
>>> print(card_1 > card_2)
True
>>> cards = [card_1, card_2]
>>> print(max(cards))
AS
The Zen of Python
The Zen of Python
● Beautiful is better than ugly.
● Explicit is better than implicit.
● Simple is better than complex.
● Complex is better than complicated.
● Flat is better than nested.
● Sparse is better than dense.
● Readability counts.
● Special cases aren't special enough to break the rules.
● Although practicality beats purity.
● Errors should never pass silently.
● Unless explicitly silenced.
● In the face of ambiguity, refuse the temptation to guess.
● There should be one-- and preferably only one --obvious way to do it.
● Although that way may not be obvious at first unless you're Dutch.
● Now is better than never.
● Although never is often better than *right* now.
● If the implementation is hard to explain, it's a bad idea.
● If the implementation is easy to explain, it may be a good idea.
● Namespaces are one honking great idea -- let's do more of those!
Python Idioms
● “The specific grammatical, syntactic, and structural character of
a given language”
● “A commonly used and understood way of expressing a fact,
idea or intention.”
Examples by Safe Hammad
http://safehammad.com/downloads/python-idioms-2014-01-16.pdf
Python Idioms
● "Programs must be written for people to read, and only incidentally for machines to execute."
- Abelson & Sussman, SICP
● “There should be one - and preferably only one - obvious way to do it.”
- The Zen of Python
● The use of commonly understood syntax or coding constructs can aid readability and clarity.
● Some idioms can be faster or use less memory than their “non-idiomatic” counterparts.
● Python's idioms can make your code Pythonic!
Make a script both importable and executable
if __name__ == '__main__':
    main()
Test for “truthy” and “falsy” values
if x:
if not x:
Test for “truthy” and “falsy” values
# GOOD
name = “Ben”
if name:
    print(“Hello %s” % name)
# BAD
if name != “”:
    print(“Hello %s” % name)
Truth
● True:
– Non-empty string
– Number not 0
– Non-empty container
(len(x) > 0)
– True
● False:
– Empty string
– Number 0
– Empty container
(len(x) == 0)
– False
– None
in
● Contains:
if x in items:
● Iteration:
for singular in plural:
in – iteration (list)
people = [“Alice”, “Bob”, “Charlie”]
# GOOD
for name in people:
    print(name)
# BAD
for i in range(len(people)):
    print(people[i])
in – iteration (dictionary)
people = {“Alice”: 23, “Bob”: 21, “Charlie”: 30}
# GOOD
for name, age in people.items():
    print(“%s is %i” % (name, age))
# BAD
for name in people:
    print(“%s is %i” % (name, people[name]))
in - contains
people = [“Alice”, “Bob”, “Charlie”]
name = “Ben”
if name in people:
    print(“in”)
else:
    print(“out”)
Swap variables
a = 1
b = 2
# GOOD
a, b = b, a
# BAD
c = a
a = b
b = c
Join
words = ['hello', 'world']
# GOOD
print(' '.join(words))
# BAD
s = ''
for word in words:
    s += word + ' '
print(s)
with – self-cleanup
# GOOD
with open('file.txt') as f:
    line = f.readline()
# BAD
f = open('file.txt')
line = f.readline()
with – self-cleanup
# GOOD
with PiCamera() as camera:
    camera.start_preview()
    sleep(2)
    camera.capture('image.jpg')
    camera.stop_preview()
# BAD
camera = PiCamera()
camera.start_preview()
sleep(2)
camera.capture('image.jpg')
camera.stop_preview()
Exceptions
people = {“Alice”: 23, “Bob”: 21, “Charlie”: 30}
name = “Ben”
# OK
if name in people:
    age = people[name]
else:
    age = None
Exceptions
people = {“Alice”: 23, “Bob”: 21, “Charlie”: 30}
name = “Ben”
# GOOD
try:
    age = people[name]
except ValueError:
    age = None
# BAD
try:
    age = people[name]
except:
    age = None
Exceptions – try/except not try/catch!
try:
    import GPIO
except ImportError:
    GPIO = None
if GPIO:
    …
else:
    print(“Cannot access GPIO”)
Exceptions – patch to work in Python 2 and 3
try:
    input = raw_input
except NameError:
    pass
Exceptions – patch to work in Python 2 and 3
from __future__ import (
    unicode_literals,
    print_function,
    division,
    absolute_import,
)
# Make Py2's str and range equivalent to Py3's
str = type('')
try:
    range = xrange
except NameError:
    pass
PEP : Python Enhancement Proposals
PEP8 - Style Guide for Python Code
● Indentation
● Tabs or spaces?
● Maximum line length
● Blank lines
● Source file encoding
● Imports
● String quotes
● Whitespace
● Comments
● Versioning
● Naming conventions
● Programming recommendations
PyPi: Python Packaging Index
● Free-for-all upload of Python packages and modules
● Namespace based
● Browsable online
● Easy to upload & update
● Easy to download
● Easy to install & upgrade
What a Python package looks like
 ├── energenie
     │ ├── energenie.py
     │ └── __init__.py
 └── setup.py
Write in C - optional
● Python modules can be written in C for optimal speed
Installing packages with pip
$ pip install energenie
$ pip3 install energenie
Virtualenv
● Isolated environment for running an appplication with specific
version dependencies
● Run multiple apps requiring different versions of libraries
● Use pip to install within a virtualenv
Secrets from the Future
● from __future__ import print_function, division
Bring Python 3 features into Python 2
2to3
● Convert a Python file, set of files or module from Python 2 to
Python 3 syntax
– Often trivial
– Sometimes requires manual intervention
– Dry run to see suggested changes first
Tips
● IPython shell
● IPython Notebook
● Trinket
● PEP8
● python.org – docs, examples, wiki
● PyPi
Community
● PyCon
– PyCon (Montreal)
– PyConUK (Coventry)
– EuroPython (Bilbao)
– PyCon Ireland (Dublin)
– EuroSciPy (Cambridge)
– Many more!
● User groups & organisations
– Campug
– London Python Dojo
– PyLadies
– Django Girls
– Python Software Foundation
Further reading
● Why Python is a Great First Language
http://blog.trinket.io/why-python/
● Python Success Stories
https://www.python.org/about/success/
● Python in Education
http://www.oreilly.com/programming/free/python-in-education.
csp
Learn Python
● Python Challenge
http://www.pythonchallenge.com/
● Python Docs
https://www.python.org/doc/
● Project Euler
https://projecteuler.net/
● Raspberry Pi Learning Resources
https://www.raspberrypi.org/resources/
● Trinket
https://trinket.io/python
Python for PHP Developers
@ben_nuttall
Raspberry Pi Foundation

Python for PHP developers