
Study notes on Python class and Julia struct+methods
Shuvomoy Das Gupta
August 11, 2025
Abstract
In this studynote, we discuss how to translate the concept of a into idiomatic Julia.
Contents
1 The Core Philosophical Difference 1
2 The ”Julia Way”: struct + Methods 1
2.1 Example: A Simple Circle 1
2.1.1 Python Implementation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
2.1.2 Native Julia Implementation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
3 Handling Circular Dependencies 1
3.1 Example: Employee and Company 1
3.1.1 Python Implementation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
3.1.2 The Idiomatic Julia Solution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1 The Core Philosophical Difference
When moving from a heavily object-oriented language like Python to Julia, the most crucial shift in thinking is understanding
how data and behavior are organized. The best practice is to not replicate a Python one-to-one. Instead, one should
embrace Julia’s paradigm of multiple dispatch.
Python’s Approach: Functionality
is bundled with the data it operates
on. You call methods on an object:
.
Julia’s Approach: Data () and func-
tionality () are decoupled. You call
a function with an object as an argument:
.
This decoupling is a core feature, not a limitation. It allows for greater flexibility and extensibility, as new methods can be
added to existing functions for any data type without modifying the original type definition.
2 The ”Julia Way”: struct + Methods
The idiomatic way to achieve the functionality of a Python class is to combine a data structure with separate functions that
operate on it.
1. Define a struct to hold data. This is analogous to the attributes in a class’s method. Use if you
need to change field values after creation.
2. Define functions that accept your struct as an argument. These are your methods. Type-annotating the argument, like
, creates a new method for the generic function .
3. Define custom constructors. These are special functions with the same name as the that provide controlled or
convenient ways to create instances.
2.1 Example: A Simple Circle
Let’s compare a implementation in both languages.
2.1.1 Python class Implementation In Python, data and methods are encapsulated within the class.
1 import math
2
3 class Circle
4 """A class representing a circle."""
5
6 def
7 if
8 raise ValueError
9
10
11
12
13 def
14 return
15
16 def
17
18 return
Python Usage & Output
1
2
3
4
5 True
2.1.2 Native Julia Implementation In Julia, we define a for data and then define functions that operate on that .
This is more extensible.
1 # 1. Define the data structure
2 mutable struct Circle
3 Float64
4 Float64
5 Float64
6 end
7
8 # 2. Define a custom constructor for validation
9 function
10 DomainError
11 return Float64 Float64 Float64
12 end
13
14 # 3. Define behavior as separate functions
15
16 function Circle
17 return
18 end
19
20
21 function Circle Real Real
22
23 return
24 end
Julia Usage & Output
1
2
3
4
5
6
7
8
Python Concept Julia Idiom
or
Custom outer constructor function
Inheritance ( ) Composition or Abstract Types ( )
A simple function call, e.g.,
/ Overload
Table 1: A quick reference for
translating Python OOP concepts
to Julia.
3 Handling Circular Dependencies
Circular dependencies, where class needs and needs , are handled seamlessly in Python due to its reference-based object
model. In Julia, a direct circular definition is impossible because a ’s memory layout must be known at compile time.
The solution involves using an as a ”forward declaration” to break the definitional cycle.
3.1 Example: Employee and Company
An works for a , and a has a list of s. This is a classic circular dependency.
3.1.1 Python Implementation Python’s reference semantics make this straightforward.
1 class Employee
2 def
3
4 None # Will hold a Company instance
5
6 class Company
7 def
8
9 # Will hold Employee instances
10
11 def
12 if is not None
13 raise ValueError{}
14
15 # Creates the circular link
Python Usage & Output
1
2
3
4
5
3.1.2 The Idiomatic Julia Solution The Julia solution requires a more deliberate structure:
1. Forward Declare: Use .
2. Define First Struct: Define , whose field is a .
3. Define Second Struct: Define .
4. Link them: Create a separate function to establish the circular reference.
1 # 1. "Forward declare" Company using an abstract type
2 abstract type AbstractCompany end
3
4 # 2. Define Employee, making it mutable
5 mutable struct Employee
6 String
7 UnionAbstractCompany Nothing
8 String # Inner constructor
9 end
10
11 # 3. Define Company as a concrete subtype
12 mutable struct Company AbstractCompany
13 String
14 VectorEmployee
15 String # Inner constructor
16 end
17
18 # 4. Create the "linker" function (note the `!`)
19 function Company Employee
20 if
21 ArgumentError
22 end
23
24 # Create the circular link
25 return
26 end
Julia Usage & Output
1
2
3
4
5
6
7
8
9
10
11