Slide 1

Slide 1 text

PYTHON FOR THE RUBY PROGRAMMER Brian Riley @btriley

Slide 2

Slide 2 text

BRIAN WHO? •Freelance programmer •Worked on many Python projects and at startups •I actually like Rubby •Once had a run in with the yakuza

Slide 3

Slide 3 text

ASSUMPTIONS •You’re a Ruby programmer •You can read Python •You may or may not have worked in Python

Slide 4

Slide 4 text

PYTHON IS READABLE print "Hello, world!" puts "Hello, world!" hello_world.py hello_world.rb

Slide 5

Slide 5 text

BUT NOT ALWAYS puts "Hello, world!" hello_world.py hello_world.rb def greet(): print "Hello, world!" if __name__ == '__main__': greet()

Slide 6

Slide 6 text

ENVIRONMENT $ python hello_world.py Hello, world! $ $ ruby hello_world.rb Hello, world! $

Slide 7

Slide 7 text

ENVIRONMENT $ python >>> print "Hello, world!" Hello, world! >>> exit() $ irb > puts "Hello, world!" Hello, world! => nil > exit

Slide 8

Slide 8 text

ZEN OF PYTHON >>> import this The Zen of Python, by Tim Peters 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!

Slide 9

Slide 9 text

ZEN OF PYTHON >>> import this The Zen of Python, by Tim Peters 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!

Slide 10

Slide 10 text

BIFS __import__() abs() all() any() apply() basestring() bin() bool() buffer() bytearray() callable() chr() classmethod() cmp() coerce() compile() complex() delattr() dict() dir() divmod() enumerate() eval() execfile() file() filter() float() format() frozenset() getattr() globals() hasattr() hash() help() hex() id() input() int() intern() isinstance() issubclass() iter() len() list() locals() long() map() max() memoryview() min() next() object() oct() open() ord() pow() print() property() range() raw_input() reduce() reload() repr() reversed() round() set() setattr() slice() sorted() staticmethod() str() sum() super() tuple() type() unichr() unicode() vars() xrange() zip()

Slide 11

Slide 11 text

BIFS __import__() abs() all() any() apply() basestring() bin() bool() buffer() bytearray() callable() chr() classmethod() cmp() coerce() compile() complex() delattr() dict() dir() divmod() enumerate() eval() execfile() file() filter() float() format() frozenset() getattr() globals() hasattr() hash() help() hex() id() input() int() intern() isinstance() issubclass() iter() len() list() locals() long() map() max() memoryview() min() next() object() oct() open() ord() pow() print() property() range() raw_input() reduce() reload() repr() reversed() round() set() setattr() slice() sorted() staticmethod() str() sum() super() tuple() type() unichr() unicode() vars() xrange() zip()

Slide 12

Slide 12 text

LEN() >>> len([1, 2, 3]) 3 >>> [1, 2, 3].length() Traceback (most recent call last): File "", line 1, in AttributeError: 'list' object has no attribute 'length' >>> [1, 2, 3].len() Traceback (most recent call last): File "", line 1, in AttributeError: 'list' object has no attribute 'len'

Slide 13

Slide 13 text

IMPORTS from sys import path import sys sys.path import django def hello_world(): print django.template.loader.render_to_string( template, {'message': "Hello, world!"} )

Slide 14

Slide 14 text

ZEN OF PYTHON >>> import this The Zen of Python, by Tim Peters 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!

Slide 15

Slide 15 text

FUNCTION() VS FUNCTION >>> def hello_world(): ... print "Hello, world!" ... >>> hello_world() Hello, world! >>> hello_world >>>

Slide 16

Slide 16 text

FUNCTION() VS FUNCTION import sys def poo(): print u"\U0001F4A9" def see_no_evil(): print u"\U0001F648" def quit(): sys.exit() def output(input): handlers = { 'poo': poo, 'see no evil': see_no_evil, 'quit': quit } handlers[input]()

Slide 17

Slide 17 text

LIST COMPREHENSIONS cool_kids = [] for user in users: if user.does_program_ruby(): cool_kids.append(user)

Slide 18

Slide 18 text

LIST COMPREHENSIONS cool_kids = [] for user in users: if user.does_program_ruby(): cool_kids.append(user)

Slide 19

Slide 19 text

LIST COMPREHENSIONS cool_kids = [user for user in users if user.does_program_ruby()] import math cubes = [math.pow(3, num) for num in list]

Slide 20

Slide 20 text

DICTIONARY COMPREHENSIONS cool_kids = {user.id: user.name for user in users if user.does_program_ruby()}

Slide 21

Slide 21 text

DECORATORS from django.contrib.auth.decorators import login_required def dashboard(request): # ... dashboard = login_required(dashboard) # the same as above @login_required def dashboard(request): # ...

Slide 22

Slide 22 text

CONTEXT MANAGERS f = open('cat.gif', 'r') # ... f.close() # same as above with open('cat.gif', 'r') as f: # ...

Slide 23

Slide 23 text

__METHODS__ class Python(object): def __init__(self, herp, derp): # I'm a constructor, duh self.herp = derp self.derp = herp

Slide 24

Slide 24 text

__METHODS__ >>> class Array(list): ... def __len__(self): ... return 999999999 ... >>> array = Array() >>> array.append(1) >>> array.append(2) >>> array.append(3) >>> array [1, 2, 3] >>> len(array) 999999999 Here be dragons

Slide 25

Slide 25 text

A STORY OF WHITESPACE >>> def give_me_space_or_give_me_death(): ... print "Death it is" File "", line 2 print "Death it is" ^ IndentationError: expected an indented block