# The is "Expando objects" in Julia?

**URL:** <https://discourse.julialang.org/t/the-is-expando-objects-in-julia/5957>\
**Category:** General Usage\
**Created:** [September 18, 2017, 11:46pm UTC](https://discourse.julialang.org/t/the-is-expando-objects-in-julia/5957 "2017-09-18T23:46:35Z")\
**Posts on this page:** 1\
**Showing post:** 6

<div class="post-metadata">

**Author:** ![karei](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/karei/32/214809_2.png) [@karei](https://discourse.julialang.org/u/karei)\
**Post date:** [January 3, 2026, 1:14pm UTC](https://discourse.julialang.org/t/the-is-expando-objects-in-julia/5957/6 "2026-01-03T13:14:39Z")

</div>

I played with the “expando object” idea and found a tiny way (≈30 lines) to get a _Python-like instance experience_ in Julia: dynamic attributes + dynamic “methods” with `obj.f(args...)` syntax, by storing everything in an `EasyConfig.Config` (nested dict) and auto-binding `self` via `getproperty`.

```julia
using EasyConfig

@kwdef mutable struct DynObj
    cfg::Config = Config()
end

_wrap(c::Config) = DynObj(c)
_wrap(x) = x

function Base.getproperty(o::DynObj, name::Symbol)
    name === :cfg && return getfield(o, :cfg)
    c = getfield(o, :cfg)

    if haskey(c, name)
        v = c[name]
        return if v isa Function
            (args...) -> v(o, args...)
        else
            _wrap(v)
        end
    else # create intermediate nodes to allow o.a.b.c = 1
        child = Config()
        c[name] = child
        return DynObj(child)
    end
end

function Base.setproperty!(o::DynObj, name::Symbol, v)
    name === :cfg && throw(ArgumentError("field :cfg is reserved"))
    getfield(o, :cfg)[name] = v isa DynObj ? v.cfg : v
    return v
end

Base.propertynames(o::DynObj; private=false) = private ? (:cfg, keys(o.cfg)...) : (keys(o.cfg)...,)
Base.delete!(o::DynObj, k::Symbol) = (delete!(o.cfg, k); o)

```

Quick demo:

```julia
o = DynObj()
o.x = 1
o.msg = "hello"

o.add = (self, y) -> self.x + y
o.greet = self -> "greet: $(self.msg)"

o.add(5) # 6
o.greet() # "greet: hello"

o.sub.name = "child"
o.sub.say = self -> "I am $(self.name)"
o.sub.say() # "I am child"

```

Caveats:

- performance is _not_ the goal here: this is fully dynamic (Dict + Any + closure binding), so it’s mostly for experimentation / prototyping.
- reading a missing property creates an empty node (nice for `o.a.b.c = ...`, but can hide typos).
- “methods” here are just function values stored in a dict; the auto-binding returns a closure, so it bypasses Julia’s normal multiple dispatch / method tables and may allocate.

Ref: [ANN: EasyConfig.jl: An easy-to-write JSON-ish data structure](https://discourse.julialang.org/t/ann-easyconfig-jl-an-easy-to-write-json-ish-data-structure/50104)

---

_[View the full topic](https://discourse.julialang.org/t/the-is-expando-objects-in-julia/5957)._
