python for php developers
TRANSCRIPT
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
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
● 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)
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(name=None):
if name:
print(“Hello %s” % name)
else:
print(“Hello”)
greeting()
greeting(“Ben”)
Functions – positional & named argumentsdef 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 – globals (read only)
pi = 3.14159265358979
def circumference(radius):
return 2 * pi * radius
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
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}
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
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 methodsclass 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● 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!
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 – 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”)
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
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
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
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
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