Ruby vs Python syntax
Index
- Printing and String Interpolation
- Nothing and Truthiness
- Boolean
- Arrays/Lists
- Hashes/Dicts
- Symbols
- Control Flow
- Methods/Functions
- Blocks, Procs, Lambdas
- Classes
Printing and String Interpolation
Ruby:
puts "value of a: %s" % a
# value of a: test
puts "value of a: #{a}"
# value of a: test
Python:
print "value of a: %s" % a
# value of a: test
print "value of a: {0}".format(a)
# value of a: test
print(f”{I}. {key} appears {wordBank[key]} times.”)
Nothing and Truthiness
Ruby:
my_var.nil?
Python:
my_var is None
Boolean
Ruby:
!false # true
# these short-circuit:
false && true # false
true || false # true
Python:
not False # True
# these short-circuit:
False and True # False
True or False # True
Arrays/Lists
Instantiation
Ruby:
a = []
b = [1,2,3]
c = Array.new
d = Array[1,2,3]
e = (1..5).to_a
Python:
a = []
b = [1,2,3]
c = list()
d = list([1,2,3])
e = list(range(5))
Operations
Ruby:
a = [1,2]; b = [3,3]
a.include?(1) # true
a + b # [1,2,3,3]
# makes shallow copies:
[a] * 2 # [[1,2],[1,2]]
a[0] # 1
a.first # 1
a[-1] # 2
a.last # 2
a.size # 2
a.length # 2
a.count # 2
b.index(3) # 0
b.count(3) # 2
Python:
a = [1,2]; b = [3,3]
1 in a # True
a + b # [1,2,3,3]
# makes shallow copies:
[a] * 2 # [[1,2],[1,2]]
a[0] # 1
a[-1] # 2
len(a) # 2
b.index(3) # 0
b.count(3) # 2
Slicing
Ruby:
vals = [a,b,c,d]
vals[1..2] # [b,c]
vals[1...3] # [b,c]
vals[-3..-2] # [b,c]
vals[-3...-1] # [b,c]
# alternate form:
# array[start_index, length]
vals[1,2] # [b,c]
vals[-3,2] # [b,c]
Python:
vals = [a,b,c,d]
vals[1:3] # [b,c]
vals[-3:-1] # [b,c]
Slicing to/from the end of list:
Ruby:
vals = [a,b,c,d]
vals[2...vals.size] # [c,d]
vals[2,vals.size] # [c,d]
vals.last(vals.size - 2) # [c,d]
vals[0...2] # [a,b]
vals[0,2] # [a,b]
vals.first(2) # [a,b]
Python:
vals = [a,b,c,d]
vals[2:] # [c,d]
vals[:2] # [a,b]
Hashes/Dicts
Ruby:
a = {}
b = {'x'=>1, 2=>2, Fixnum=>3}
c = Hash.new
d = Hash[[['x',1],[2,2]]]
e = Hash.new { |hash,key| hash[key] = [] }
# Blocks! Getting ahead of myself...
Python:
a = {}
b = {'x':1, 2:2, int:3}
c = dict()
d = dict([['x',1],[2,2]])
e = defaultdict(list) # from collections module
Ruby:
a = {'x'=>2}
a['y'] = 5
a.has_key?('y') # true
a.key?('y') # true
a.delete('y') # 5
!a.include?('y') # true
a.keys # ['x']
a.values # [2]
a.to_a # [['x',2]]
Python:
a = {'x':2}
a['y'] = 5
'y' in a # True
del a['y']
'y' not in a # True
a.keys() # ['x']
a.values() # [2]
a.items() # [('x',2)]
Symbols
Ruby:
:foo.to_s # "foo"
"foo".intern # :foo
"foo".to_sym # :foo
:foo == :foo # true
:foo.object_id == :foo.object_id # true
Control Flow
If-block
Ruby:
if true
puts "Gets here"
elsif false
puts "Doesn't get here"
else
puts "Definitely not getting here"
end
Python:
if True:
print "Gets here"
elif False:
print "Doesn't get here"
else:
print "Definitely
Inline if:
Ruby:
if answer then "right" else "wrong" end
(answer) ? "right" : "wrong"
puts "You're right!" if answer
puts "You're right!" unless !answer
Python:
"right" if answer else "wrong"
print "You're right!" if answer
For-loop
Ruby:
for i in 0..2
puts i
end
(0..2).each { |i| puts i }
Python:
for i in range(3):
print i
While-loop
Ruby:
while true
# do stuff
end
until false
# do stuff
end
Python:
while True:
# do stuff
Methods/Functions
Ruby:
def myfunc
puts "Hello!"
end
Python:
def myfunc():
print "Hello!"
Ruby:
def myfunc
1 + 1
end
myfunc # 2
def myfunc2
return "foo"
"nope"
end
myfunc # "foo"
Python:
def myfunc():
1 + 1
myfunc # None
def myfunc2():
return "foo"
myfunc # "foo"
Ruby:
def myfunc(x, y=2)
x + y
end
myfunc(2) # 4
myfunc(2,3) # 5
Python:
def myfunc(x, y=2):
return x + y
myfunc(2) # 4
myfunc(2,3) # 5
Extra arguments as array
Ruby:
def myfunc(x, y=2, *args)
args
end
myfunc(1, 2, 3, 4, 5) # [3,4,5]
Python:
def myfunc(x, y=2, *args):
return args
myfunc(1, 2, 3, 4, 5) # (3,4,5)
Ruby:
def myfunc(req, optional=2, *args,
foo: 'bar', **options)
p args
p foo
p options
end
myfunc(1, 2, 3, hey:'there', hi:3)
# [3]
# "bar"
# {:hey=>"there", :hi=>3}
Python:
def myfunc(req, optional=2, *args, **kwargs):
print args
print kwargs
myfunc(1,2,3, hey='there', hi=3)
# (3,)
# {'hi': 3, 'hey': 'there'}
Blocks, Procs, Lambdas
Ruby:
def foreach(arr, &block)
puts "block class: #{block.class}"
for i in 0...arr.size
block.call(arr[i]) # passes arr[i] to the block
end
end
foreach([1,2,3]) { |x| puts x }
# block class: Proc
# 1
# 2
# 3
Python:
def foreach(arr, myfunc):
for i in range(len(arr)):
myfunc(arr[i])
foreach([1,2,3], lambda x: print x)
# this is the equivalent of the Ruby code but
# won't work because lambdas in Python must
# contain 1 expression -- a SyntaxError is
# thrown when they contain statements like "print"
Ruby:
double = Proc.new { |x| x * 2 }
double.call(3) # 6
Python:
double = lambda x: x * 2
double(3) # 6
Iterating
Ruby:
[1,2,3].each { |x| puts x }
# 1
# 2
# 3
[:a,:b,:c].each_with_index do
|letter, index| puts "#{index} #{letter.inspect}"
end
# 0 :a
# 1 :b
# 2 :c
Python:
for x in [1,2,3]:
print x
# 1
# 2
# 3
for index, letter in enumerate(['a','b','c']):
print index, letter
# 0 a
# 1 b
# 2 c
Mapping
Ruby:
a = [1,2,3]
a.map { |x| x**2 } # [1,4,9]
# map returns a new array
# use map! to mutate the original
a.collect { |x| x**2 } # [1,4,9]
# collect is an alias of map
Python:
a = [1,2,3]
[x**2 for x in a] # [1,4,9]
map(lambda x: x**2, a) # [1,4,9]
Reducing
Ruby:
a = [1,2,3]
a.reduce(:+) # 6 (uses :+ method on Fixnum)
a.reduce(10, :+) # 16 (initial value of 10)
a.reduce(10) { |sum,x| sum + x } # 16
# inject is an alias of reduce
Python:
a = [1,2,3]
import operator
reduce(operator.add, a) # 6
reduce(operator.add, a, 10) # 16
reduce(lambda sum,x: sum + x, a, 10) # 16
# unfortunately there's no pleasant way to
# reduce with a comprehension
Filtering
Ruby:
a = [1,2,3]
a.select { |x| x.even? } # [2]
a.find_all { |x| x.odd? } # [1,3]
Python:
a = [1,2,3]
[x for x in a if x % 2 == 0] # [2]
filter(lambda x: x % 2 == 1, a) # [1,3]
Ruby:
# using \ to write across multiple lines
(0...20).select { |x| x.odd? } \
.collect { |x| x**3 } \
.inject(0, :+)
# 19900
Python:
# using \ to write across multiple lines
import operator
reduce(operator.add, \
[x**3 for x in range(20) \
if x % 2 == 1], 0)
# 19900
Classes
Ruby:
class Person
attr_reader :name # getter for name
attr_accessor :mood # getter/setter for mood
@@count = 0 # class var
# constructor
def initialize(name, mood=:happy)
@name = name # instance var
@mood = mood # instance var
@@count += 1
end
def self.count # class method
@@count
end
end
Person.count # 0
bob = Person.new('Bob')
bob.mood # :happy
Person.count # 1
amy = Person.new('Amy')
Person.count # 2
Python:
class Person:
count = 0 # class var
# constructor
# all instance methods have 'self' as 1st param
def __init__(self, name, mood='happy'):
self.name = name # instance var
self.mood = mood # instance var
Person.count += 1
# class methods have 'cls' as 1st param
@classmethod
def get_count(cls):
return cls.count
Person.count # 0
bob = Person('Bob')
bob.mood # 'happy'
Person.count # 1
amy = Person('Amy')
Person.get_count() # 2