# Is it reasonable to mimic a Python class with mutable structs?

**URL:** https://discourse.julialang.org/t/is-it-reasonable-to-mimic-a-python-class-with-mutable-structs/57516
**Category:** New to Julia
**Created:** [March 19, 2021, 6:22am UTC](https://discourse.julialang.org/t/is-it-reasonable-to-mimic-a-python-class-with-mutable-structs/57516 "2021-03-19T06:22:23Z")
**Posts on this page:** 17
**Page:** 1

<div class="post-metadata">

### Author: ![Nicholaswogan](https://avatars.discourse-cdn.com/v4/letter/n/f1d935/32.png) [@Nicholaswogan](https://discourse.julialang.org/u/Nicholaswogan)
#### Post date: [March 19, 2021, 6:22am UTC](https://discourse.julialang.org/t/is-it-reasonable-to-mimic-a-python-class-with-mutable-structs/57516/1 "2021-03-19T06:22:23Z")

</div>

Just beginning to learn Julia. I’ve realized that you can mimic a Python class using a `module` and `mutable structs`. For example,

```julia
module MimicPyClass

mutable struct Self{T<:AbstractFloat,D<:Integer}
    a::T
    b::T
    n::D
end

function __init__ ()
    return Self(1.0,2.0,10)
end
self = __init__ ()
    
function method1(;self=self)
    self.n += 1
    nothing
end

function method2(;self=self)
    return self.a + self.b
end

end
mim = MimicPyClass

println(mim.self.n)
mim.method1()
println(mim.self.n)

out = mim.method2()
println(out)

```

The only difference is that you need one more layer (which is a mutable struct) between the fake-class and the “attributes”. Is this a reasonable way to construct a larger project, which involves lots of module data which is used in many different methods? Thanks!

---

<div class="post-metadata">

### Author: ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)
#### Post date: [March 19, 2021, 6:47am UTC](https://discourse.julialang.org/t/is-it-reasonable-to-mimic-a-python-class-with-mutable-structs/57516/2 "2021-03-19T06:47:09Z")

</div>

You can’t create two instances of this class I think, so why do you want to do this? In my experience it’s good to let go of the wish to have obj.method() syntax. method(obj, args…) is not worse to write (does have worse auto complete, though) and it’s more powerful because other people can extend your functions for their types if you do it correctly. That might not be your priority now, but you benefit from this type of coding all over the ecosystem, so it’s good to get acquainted with this way of thinking

---

<div class="post-metadata">

### Author: ![nilshg](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nilshg/32/2283_2.png) [@nilshg](https://discourse.julialang.org/u/nilshg)
#### Post date: [March 19, 2021, 6:51am UTC](https://discourse.julialang.org/t/is-it-reasonable-to-mimic-a-python-class-with-mutable-structs/57516/3 "2021-03-19T06:51:01Z")

</div>

Jeff answered a question on this some time ago here: [oop - How to create a "single dispatch, object-oriented Class" in julia that behaves like a standard Java Class with public / private fields and methods - Stack Overflow](https://stackoverflow.com/questions/39133424/how-to-create-a-single-dispatch-object-oriented-class-in-julia-that-behaves-l/39150509#39150509)

---

<div class="post-metadata">

### Author: ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)
#### Post date: [March 19, 2021, 7:26am UTC](https://discourse.julialang.org/t/is-it-reasonable-to-mimic-a-python-class-with-mutable-structs/57516/4 "2021-03-19T07:26:27Z")

</div>

You can probably create some awkward version of this in Julia. But in that case you should probably rather use python.

Doing this for a larger project seems wasteful. Why not use idiomatic Julia?

---

<div class="post-metadata">

### Author: ![Skoffer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/skoffer/32/378_2.png) [@Skoffer](https://discourse.julialang.org/u/Skoffer)
#### Post date: [March 19, 2021, 8:29am UTC](https://discourse.julialang.org/t/is-it-reasonable-to-mimic-a-python-class-with-mutable-structs/57516/5 "2021-03-19T08:29:48Z")

</div>

Actually, there is no need to mimic python class, because it is already exists in Julia. In a sense, python classes are subset of Julia capabilities. Compare this two implementations

```python
class PyClass:
   def __init__ (self):
      self.a = 1.0
      self.b = 2.0
      self.n = 10

   def method1(self):
      self.n += 1

   def methof2(self):
       return self.a + self.b

mim = PyClass()
mim.method1()
mim.method2()

```

It can be written as following Julia code:

```julia
mutable struct PyClass
   a::Float64
   b::Float64
   n::Int
end

PyClass() = PyClass(0.0, 0.0, 0)
function __init__ (self::PyClass)
  self.a = 1.0
  self.b = 2.0
  self.n = 10
end

function method1(self::PyClass)
   self.n += 1
   nothing
end

function method2(self::PyClass)
  return self.a + self.b
end

mim = __init__ (PyClass())
method1(mim)
method2(mim)

```

If you look closely, you’ll see, that there is almost no difference between python and julia definitions. The only observable difference is slight change of syntax, but in a sense, Julia is more consistent.

In python you have  
definition: method - class instance - arguments  
usage: class instance - dot - method - arguments

In Julia you have  
definition: method - class instance - arguments  
usage: method - class instance - arguments

So, what am I trying to say, it’s rather easy to move python class code to Julia: you should do the same things, just use different (and more consistent) notation when you are calling methods of these “classes”.

By the way, do you know that you can use Julia style in python?

```python
mim = PyClass()

PyClass.method1(mim)
print(mim.n) # 11

def method3(self):
    print("Hello")

PyClass.method3 = method3

mim.method3() # prints Hello
PyClass.method3(mim) # prints Hello

```

It’s just that Julia can bind method to the type of the argument, so there is no need in adding `PyClass` at the outside method definition.

---

<div class="post-metadata">

### Author: ![FPGro](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fpgro/32/20822_2.png) [@FPGro](https://discourse.julialang.org/u/FPGro)
#### Post date: [March 19, 2021, 8:55am UTC](https://discourse.julialang.org/t/is-it-reasonable-to-mimic-a-python-class-with-mutable-structs/57516/6 "2021-03-19T08:55:08Z")

</div>

Completely agree with @Skoffer here. Just a small thing:

> [@Skoffer](#):
>
> ```julia
> function __init__ (self::PyClass)
> self.a = 1.0
> self.b = 2.0
> self.n = 10
> end
> 
> ```

currently returns 10, you should put a `return self` at the end to get the instance back.

Also, if you desparately need ` __init__ ` to work like it does in Python, you can pretend that it is your constructor with:

```julia
julia> mutable struct PyClass2
          a::Float64
          b::Float64
          n::Int
          PyClass2() = __init__ (new())
       end

julia> function __init__ (self::PyClass2)
         self.a = 1.0
         self.b = 2.0
         self.n = 10
         return self
       end

julia> mim = PyClass2()
PyClass2(1.0, 2.0, 10)

```

Although personally, I find the idiomatic julian way to be much more readable and clear. Feel free to drop ` __init__ ` and never look back!

---

<div class="post-metadata">

### Author: ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)
#### Post date: [March 19, 2021, 3:20pm UTC](https://discourse.julialang.org/t/is-it-reasonable-to-mimic-a-python-class-with-mutable-structs/57516/7 "2021-03-19T15:20:21Z")

</div>

Uh, just don’t put a function named ` __init__ ` into a module or you might get some very strange behaviour. ` __init__ ()` is called whenever a module is loaded.

---

<div class="post-metadata">

### Author: ![Nicholaswogan](https://avatars.discourse-cdn.com/v4/letter/n/f1d935/32.png) [@Nicholaswogan](https://discourse.julialang.org/u/Nicholaswogan)
#### Post date: [March 19, 2021, 4:22pm UTC](https://discourse.julialang.org/t/is-it-reasonable-to-mimic-a-python-class-with-mutable-structs/57516/8 "2021-03-19T16:22:31Z")

</div>

Thanks so much for all these responses! All very useful. DNF, and several others said something like

> Why not use idiomatic Julia?

I’ve read [the style guide](https://docs.julialang.org/en/v1/manual/style-guide/) but I’m still having issues imagining how to do a big project using idiomatic Julia. Is there a project on Github, that is relatively simple and understandable (!), which will give me a sense for how to use idiomatic Julia?

Some background: My research group uses [a model of atmospheric chemistry](https://github.com/Nicholaswogan/PhotochemPy) which was originally written in Fortran 77. I’ve tried to improve it by moving to Fortran 90, but it is still a bit of a disaster because it rests on a weak foundation of the original code. I think I want to propose, for a post-doc project, to re-write the photochemical model from the ground up in Julia. But before starting, I’d like to have a very solid understanding of how to do things best/fastest in Julia. Perhaps the end product should work something like this below? Advice and thoughts are welcome.

```julia
using PhotoChem
prob = PhotoProblem("inputfile1.yaml","inputfile2.yaml","inputfile3.yaml")
sol1 = steady_state(prob) # Find steady state of ODEs using the steady-state solvers in DifferentialEquations.jl
sol2 = integrate(prob,[0.0,100.0]) # ODE integration from 0 to 100 s using DifferentialEquations.jl

```

---

<div class="post-metadata">

### Author: ![tamasgal](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamasgal/32/27946_2.png) [@tamasgal](https://discourse.julialang.org/u/tamasgal)
#### Post date: [March 19, 2021, 4:26pm UTC](https://discourse.julialang.org/t/is-it-reasonable-to-mimic-a-python-class-with-mutable-structs/57516/9 "2021-03-19T16:26:56Z")

</div>

Just a tiny side-note, which might also shed some light on how things are working in Python:

```python
>>> class Foo:
... def greet(self, name):
... print(f"servus {name}")

>>> f = Foo()

>>> f.greet("Tom")
servus Tom

>>> Foo.greet(f, "Tom")
servus Tom

```

Here, you can see single dispatch in action and `Foo` (the class itself) is basically just a namespace, so to say `;)`

---

<div class="post-metadata">

### Author: ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)
#### Post date: [March 19, 2021, 4:47pm UTC](https://discourse.julialang.org/t/is-it-reasonable-to-mimic-a-python-class-with-mutable-structs/57516/10 "2021-03-19T16:47:10Z")

</div>

> [@Nicholaswogan](#):
>
> Perhaps the end product should work something like this below? Advice and thoughts are welcome.
> 
> ```julia
> using PhotoChem
> prob = PhotoProblem("inputfile1.yaml","inputfile2.yaml","inputfile3.yaml")
> sol1 = steady_state(prob) # Find steady state of ODEs using the steady-state solvers in DifferentialEquations.jl
> sol2 = integrate(prob,[0.0,100.0]) # ODE integration from 0 to 100 s using DifferentialEquations.jl
> 
> ```

Yes, that looks like the right idea. If you have a python class which looks like:

```py
# foo.py

class Bar:
  def __init__ (self, a):
    self.a = a
    self.b = a + 1
  def do_something(self, c):
    print(self.b + c)

```

then your Julia code would look like:

```julia
module Foo

export Bar, do_something

struct Bar # could also be a `mutable struct` if you want to be able to mutate `a` and `b` later
  a::Int  
  b::Int  
end
# By default, the `struct` definition creates a convenient constructor 
# which lets you do `Bar(a, b)`. Since our Python code had a constructor 
# which took just `a`, we can create another constructor matching
# that signature:

function Bar(a)
  Bar(a, a + 1)
end

function do_something(bar::Bar, c)
  println(bar.b + c)
end

end

```

---

<div class="post-metadata">

### Author: ![Eben60](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/eben60/32/13475_2.png) [@Eben60](https://discourse.julialang.org/u/Eben60)
#### Post date: [March 20, 2021, 11:24am UTC](https://discourse.julialang.org/t/is-it-reasonable-to-mimic-a-python-class-with-mutable-structs/57516/11 "2021-03-20T11:24:23Z")

</div>

> [@Nicholaswogan](#):
>
> But before starting, I’d like to have a very solid understanding of how to do things best/fastest in Julia.

It may be difficult to get a solid understanding “before starting”. So I’d suggest to start by formulating some specific small to middle-sized real problem and try to solve it in Julia, asking spesific questions here as you go. You could then even call this Julia computation from your current Python wrapper package.

On a general note, mimicking Python objects is technically to a large extent possible, and this is what many of those who are/were about to migrate a Python software to Julia would be initially planning (me too), before finding out its not worth it.

---

<div class="post-metadata">

### Author: ![Eben60](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/eben60/32/13475_2.png) [@Eben60](https://discourse.julialang.org/u/Eben60)
#### Post date: [March 20, 2021, 8:34pm UTC](https://discourse.julialang.org/t/is-it-reasonable-to-mimic-a-python-class-with-mutable-structs/57516/12 "2021-03-20T20:34:45Z")

</div>

> [@DNF](#):
>
> You can probably create some awkward version of this in Julia

Just another awkward version 😀

```julia
mutable struct Foo
   a::Int
   obj::Foo
   inc_a::Function
   function Foo(a)
      x = new()
      x.a = a

      function inc_a(i)
         x.a += i
         return nothing
      end

      x.inc_a = inc_a
      x.obj = x
   end
end

```

```julia
julia> f1 = Foo(1); f2 = Foo(2);
julia> f1.a
1
julia> f2.a
2
julia> f1.inc_a(10); f1.a
11
julia> f2.inc_a(20); f2.a
22

```

By the way - how can I specify the type of the field `inc_a` ?  
**EDIT** : see the next post.

---

<div class="post-metadata">

### Author: ![Henrique\_Becker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/henrique_becker/32/15443_2.png) [@Henrique\_Becker](https://discourse.julialang.org/u/Henrique_Becker)
#### Post date: [March 20, 2021, 8:52pm UTC](https://discourse.julialang.org/t/is-it-reasonable-to-mimic-a-python-class-with-mutable-structs/57516/13 "2021-03-20T20:52:28Z")

</div>

> [@Eben60](#):
>
> By the way - how can I specify the type of the field `inc_a` ?

I am not sure this is possible, unless you meant `Function` (you probably can annotate it as `::Function`), but to annotate it with the exact type you need to get the type of the closure after it is lowered and externalized. Luckily, they will be closures of the same type:

```julia
julia> f(x) = y -> (x + y)
f (generic function with 1 method)

julia> g = f(10)
#1 (generic function with 1 method)

julia> h = f(11)
#1 (generic function with 1 method)

julia> typeof(g) === typeof(h)
true

julia> typeof(h)
var"#1#2"{Int64}

```

---

<div class="post-metadata">

### Author: ![Eben60](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/eben60/32/13475_2.png) [@Eben60](https://discourse.julialang.org/u/Eben60)
#### Post date: [March 20, 2021, 8:58pm UTC](https://discourse.julialang.org/t/is-it-reasonable-to-mimic-a-python-class-with-mutable-structs/57516/14 "2021-03-20T20:58:24Z")

</div>

> [@Henrique\_Becker](#):
>
> you probably can annotate it as `::Function` )

Yes, this worked, thank you

---

<div class="post-metadata">

### Author: ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)
#### Post date: [March 21, 2021, 10:02am UTC](https://discourse.julialang.org/t/is-it-reasonable-to-mimic-a-python-class-with-mutable-structs/57516/15 "2021-03-21T10:02:08Z")

</div>

> [@Nicholaswogan](#):
>
> still having issues imagining how to do a big project using idiomatic Julia. Is there a project on Github, that is relatively simple and understandable (!), which will give me a sense for how to use idiomatic Julia?

I think that learning by doing is the best way. Start coding, ask questions here (like you did), occasionally revisit code and refactor.

---

<div class="post-metadata">

### Author: ![foobar\_lv2](https://avatars.discourse-cdn.com/v4/letter/f/ee59a6/32.png) [@foobar\_lv2](https://discourse.julialang.org/u/foobar_lv2)
#### Post date: [March 21, 2021, 12:23pm UTC](https://discourse.julialang.org/t/is-it-reasonable-to-mimic-a-python-class-with-mutable-structs/57516/16 "2021-03-21T12:23:30Z")

</div>

> [@Nicholaswogan](#):
>
> Is there a project on Github, that is relatively simple and understandable (!), which will give me a sense for how to use idiomatic Julia?

For this, I really recommend reading lots of `Base` code (ie [GitHub - JuliaLang/julia: The Julia Programming Language](https://github.com/julialang/julia/)). This has two advantages: First, it gives you lots of additional understanding how the standard library works; second, this is _the_ canonical example for “idiomatic” code (ie how the language is meant to work – literally, and bidirectionally: Not just is Base written to work well with the language primitives, the language primitives and compiler are also written to work well for Base).

Sure you won’t read all of it; sure it ain’t all perfect, and many things can be done simpler for smaller projects that don’t aim for that level of generality and API stability, and don’t have the issue of participating in the bootstrap process. But many parts are relatively self-contained, and shockingly readable.

If you want more self-contained, stdlib is also attractive: This gives a feel for smaller codebases, instead of sprawling behemoths like Base. [GitHub - sbromberger/LightGraphs.jl: An optimized graphs package for the Julia programming language](https://github.com/JuliaGraphs/LightGraphs.jl) is also a pretty contained, well-designed and readable project.

For your specific project, you probably rely on the DiffEq ecosystem more than julia-the-language. So you should maybe read code from your direct upstream or siblings (other packages that implement specific models). I have no idea about readability or internal code quality of these projects, though. You might consider shooting at-ChrisRackauckas a message on slack.

---

<div class="post-metadata">

### Author: ![Eben60](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/eben60/32/13475_2.png) [@Eben60](https://discourse.julialang.org/u/Eben60)
#### Post date: [April 1, 2021, 10:16am UTC](https://discourse.julialang.org/t/is-it-reasonable-to-mimic-a-python-class-with-mutable-structs/57516/17 "2021-04-01T10:16:10Z")

</div>

Checking my Zotero bookmarks I came across this post: [Workflow for converting Python scripts - #3 by tamasgal](https://discourse.julialang.org/t/workflow-for-converting-python-scripts/32737/3)
