pythonswiftmonkeypatchingkeypaths

Is there a Python equivalent for Swift's @dynamicMemberLookup?


In Swift, you can define @dynamicMemberLookup (see documentation) to get direct access to properties that are nested inside another type. Is there a Python equivalent?

Example of what I want to achieve with Python

Let's say I have a class with members, e.g.:

c = OuterClass()
c.inner_class = ClassWithManyMembers()
c.inner_class.member1 = "1"
c.inner_class.member2 = "2"
c.inner_class.member3 = "3"

I would like to be able to get/set those members without having to type the inner_class every time:

print(c.member1)  # prints "1"
c.member1 = 3
print(c.member1)  # prints "3"

Example in Swift (Source):

Dynamic member lookup by member name

@dynamicMemberLookup
struct DynamicStruct {
    let dictionary = ["someDynamicMember": 325,
                      "someOtherMember": 787]
    subscript(dynamicMember member: String) -> Int {
        return dictionary[member] ?? 1054
    }
}
let s = DynamicStruct()

// Use dynamic member lookup.
let dynamic = s.someDynamicMember
print(dynamic)
// Prints "325"

Dynamic member lookup by key path

struct Point { var x, y: Int }

@dynamicMemberLookup
struct PassthroughWrapper<Value> {
    var value: Value
    subscript<T>(dynamicMember member: KeyPath<Value, T>) -> T {
        get { return value[keyPath: member] }
    }
}

let point = Point(x: 381, y: 431)
let wrapper = PassthroughWrapper(value: point)
print(wrapper.x)

My only idea in Python would be to monkey-patch all nested properties directly to the outer class.


Solution

  • Generally, you can just save a reference to the inner object when you want to make repeated accesses to it.

    c = OuterClass()
    c.inner_class = ClassWithManyMembers()
    
    ic = c.inner_class
    print(ic.member1)
    print(ic.member2)
    print(ic.member3)
    
    ic.member1 = "5"