Есть ли библиотека для выполнения последовательности операций индексации и `getattr`? - PullRequest
1 голос
/ 05 июля 2019

У меня есть куча объектов, у них есть члены, у их членов есть члены ..., где-то мне нужно выполнить индексацию, а затем получить доступ к членам ...

Итак, в основном я хочу получить obj.member1.member2[3].member4, а также хочу назначить obj.member1[2].member3.member4 = new_value. Я хочу сгенерировать эти «пути», которые описывают, когда использовать getattr, а когда динамически использовать индексирование. Есть ли библиотека для этого? Я представляю интерфейс как

get_obj_path(obj, (("member1", "a"), ("member2", "a"), (3, "i"), ("member4", "a")))

и

assign_obj_path(obj, (("member1", "a"), (2, "i"), ("member3", "a"), ("member4", "a")), new_value)

1 Ответ

1 голос
/ 05 июля 2019

Вы можете реализовать эти функции самостоятельно:

def get_obj_path(obj, path):
    if not path:
        return obj
    (key, kind), *path = path
    if kind == "a":
        obj = getattr(obj, key)
    elif kind == "i":
        obj = obj[key]
    else:
        raise ValueError(f"invalid kind '{kind}'.")
    return get_obj_path(obj, path)

def assign_obj_path(obj, path, value):
    (key, kind), *path = path
    if not path:
        if kind == "a":
            setattr(obj, key, value)
        elif kind == "i":
            obj[key] = value
        else:
            raise ValueError(f"invalid kind '{kind}'.")
    else:
        if kind == "a":
            obj = getattr(obj, key)
        elif kind == "i":
            obj = obj[key]
        else:
            raise ValueError(f"invalid kind '{kind}'.")
        assign_obj_path(obj, path, value)

# Test
class MyClass: pass
obj1 = MyClass()
obj1.i = 1
obj2 = MyClass()
obj2.lst = [obj1]
assign_obj_path(obj2, (("lst", "a"), (0, "i"), ("i", "a")), 2)
print(get_obj_path(obj2, (("lst", "a"), (0, "i"), ("i", "a"))))
# 2
...