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
- You love flexible, expressive syntax (blocks, metaprogramming)
- You’re building with Rails
- You want
method_missing, monkey-patching, and DSLs - Your team values convention-over-configuration
When to Choose Python
- You prioritize readability and one-obvious-way
- You need data science / ML libraries (NumPy, Pandas, PyTorch)
- You want async I/O with
asyncio - Your team is more comfortable with explicitness