Rubyist's guide to Python

Monica Georgieva @spiralnegative

Main differences

Use cases

Ruby

quick development of web applications
fast prototyping
command line utilities, tooling and sysadmin work

Python

data-heavy sites and servers
usage by non-programmers
big data, math problems and scientific research

Characteristics

Ruby

freedom and flexibility to do things in different ways
expressive, elegant and efficient
very web focused and innovates quicker

Python

explicit - simplicity over flexibility
quicker to learn, conservative and efficient
stable and diverse, but innovates slower

Popular applications

Ruby

Basecamp, Twitter (originally), GitHub, Airbnb

Python

YouTube, Instagram, Spotify, Reddit

Libraries

Ruby

gem install pry


Python

pip3 install numpy

Testing and debugging

Ruby

RSpec and Cucumber
pry and byebug

Python

PyTest and unittest
pdb and PuDB

Ruby vs Python

Closures

Ruby


[5,6,7].each { |n| puts "#{n}!!!" }
          

def return_from_proc
  a = Proc.new { return 10 }.call
  puts "This will never be printed."
end
          

def return_from_lambda
  a = lambda { return 10 }.call
  puts "The lambda returned #{a}, and this will be printed."
end
  

Closures

Python


def outer_function(x):
  def inner_increment(x):
      return x + 2

  y = inner_increment(x)
  print(x, y)

outer_function(5)
# 5 7
  

Functions as arguments

Ruby


def run_proc_with_random_number(proc)
  proc.call(rand)
end

proc = Proc.new { |number| puts "#{number}!!!" }
run_proc_with_random_number(proc)
  

Functions as arguments

Python


from random import *

def run_with_random_number(func):
  func(random())

def exclaim(number):
  print(f"{number}!!!")

run_with_random_number(exclaim)
  

Multiple inheritance

Ruby


module Cupcake
  def sprinkle; end
end

module Cookie
  def glaze; end
end

class Dessert
  include Cupcake
  include Cookie

  def bake; end
end
  

Multiple inheritance

Python


class Cupcake:
  def sprinkle(self):
      pass

class Cookie:
  def glaze(self):
      pass

class Dessert(Cupcake, Cookie):
  def bake(self):
      pass
  

To return or not to return?

Ruby


def valid_dna?(sequence)
  sequence.chars.all? { |char| 'ACGT'.include? char }
end
  

Python


def valid_dna(sequence):
  return all(char in 'ACGT' for char in sequence)
  

The missing case

Ruby


case x
when 0
  puts "That's a good start"
when 1..5
  puts 'Getting there...'
when 'Ruby'
  puts 'Banitsa!'
when 42
  puts 'The answer'
else
  puts "What should I do with #{x}?"
end
  

The missing case

Python


def f(x):
  return {
      0: "That's a good start",
      5: 'Getting there...',
      'Ruby': 'Banitsa',
      42: 'The answer'
  }.get(x, f'What should I do with {x}')
  

Ternary operators

Ruby


awake && ready ? 'go to work' : 'wake up and get ready'
if awake && ready then 'go to work' else 'wake up and get ready' end
  

Python


'go to work' if awake and ready else 'wake up and get ready'
  

Flatten and reduce

Ruby


numbers = [[1, 2], [3, 4, 5], [6]]
numbers.flatten
# => [1, 2, 3, 4, 5, 6]

numbers = _
numbers.reduce(100, :+)
# => 121
  

Flatten and reduce

Python


numbers = [[1, 2], [3, 4, 5], [6]]
[y for x in numbers for y in x]
# [1, 2, 3, 4, 5, 6]

import itertools
list(itertools.chain(*numbers))
# [1, 2, 3, 4, 5, 6]

numbers = _
from functools import reduce
reduce((lambda x, y: x + y), [100] + numbers)
  

Adding an element to a list

Ruby


animals = []
animals[5] = 'rabbit'
animals
# => [nil, nil, nil, nil, nil, 'rabbit']
  

Python


animals = []
animals[5] = 'rabbit'
# IndexError: list assignment index out of range
  

Thank you!