Ruby vs Python Naming Conventions
Variables
Both Ruby and Python prefer snake_case for variable names, reflecting clarity and natural readability.
Ruby makes scope explicit through sigils. Python relies on lexical scope and keywords.
Ruby → snake_case: user_name
Python → snake_case: user_name
Constants → SCREAMING_SNAKE_CASE
Ruby warns when reassigned; Python allows reassignment but by convention treated as constant.
Ruby globals → $var (visible everywhere, discouraged in idiomatic code)
Ruby instance → @var (object-specific)
Ruby class var → @@var (shared across class hierarchy, rarely used)
Ruby symbols → :name (immutable identifier, no Python equivalent)
Python uses no sigils. Variables rely on naming and scoping rules:
local variables → inside function
instance variables → self.name
class variables → ClassName.name or cls.name
globals → declared with
globalkeyword
Methods
Both languages use snake_case for methods and functions. Ruby often signals intent via punctuation; Python via naming and documentation.
Ruby predicate → empty?, valid?, nil?
Python predicate → is_empty(), is_valid(), is_none()
Ruby bang (mutating) → save!, sort!, downcase!
Python → no bang; mutating vs non-mutating versions have distinct names (e.g. list.sort() vs sorted())
Private
Ruby → under private keyword
Python → naming convention _internal() for weak privacy, __dunder__ for name mangling and magic methods
Special Ruby idioms
? marks a method returning boolean
! marks a method with side effects
These cues make method intent visually obvious.
Python, valuing explicitness, avoids punctuation and relies on docstrings and naming.
Classes & Modules
Ruby → CamelCase: UserProfile
Python → PascalCase: UserProfile
Both follow the same convention but Ruby applies it universally to constants, modules, and classes.
Files → snake_case.rb / snake_case.py
Directories → snake_case/
In Ruby, a file’s name maps directly to its class or module for autoloading (Zeitwerk):
app/models/user_profile.rb defines class UserProfile.
Python’s import system only requires consistency:
user_profile.py defines class UserProfile, but the import path determines visibility, not naming.
Meta
Ruby uses concise macros for attributes:
attr_accessor :name → generates name and name=
Python uses decorators:
@property for getters
@name.setter for setters
Ruby → user.active?
Python → user.is_active
Ruby block vars → do |x| ... end
Python loop vars → for x in iterable:
Example Ruby
class UserAccount
  attr_accessor :first_name, :last_name, :status
  def full_name
    "#{first_name} #{last_name}"
  end
  def active?
    @status == :active
  end
  def deactivate!
    @status = :inactive
  end
end
Logfire project URL: https://logfire-us.pydantic.dev/baris/blog