Ruby vs Python

Side-by-side comparison of Ruby and Python — syntax, idioms, and trade-offs.

Ruby and Python are both dynamic, expressive languages with strong communities. Ruby optimizes for developer happiness with flexible syntax; Python optimizes for readability with one-obvious-way-to-do-it.

Feature Ruby Python
Philosophy Principle of least surprise There should be one obvious way
Typing Dynamic, interpreted Dynamic, interpreted
Variable x = 42 x = 42
Function def add(a, b) = a + b def add(a, b): return a + b
Array nums = [1, 2, 3] nums = [1, 2, 3]
Hash / Dict { a: 1, b: 2 } {"a": 1, "b": 2}
Class class User; attr_accessor :name; end class User: pass
Block / Lambda [1,2,3].map { |n| n * 2 } [n * 2 for n in [1,2,3]]
Error handling begin/rescue/end try/except/finally
Loop 5.times { |i| } for i in range(5):
String interp "Hello #{name}" f"Hello {name}"
Concurrency Threads (GIL) / Ractors (3.0+) Threads (GIL) / asyncio
Module require / Bundler import / pip
Testing rspec pytest
Null nil None
Method missing method_missing __getattr__

Concurrency Comparison

Ruby — Thread + Mutex

mutex = Mutex.new
counter = 0
threads = 10.times.map do
  Thread.new { mutex.synchronize { counter += 1 } }
end
threads.each(&:join)

Python — asyncio

import asyncio

async def fetch(url):
    await asyncio.sleep(0.1)
    return f"result from {url}"

async def main():
    results = await asyncio.gather(
        fetch("a"), fetch("b")
    )

asyncio.run(main())

Both have a GIL that limits CPU-parallelism in threads. Ruby 3’s Ractor enables true parallelism; Python uses multiprocessing or asyncio for concurrency.

When to Choose Ruby

When to Choose Python