В common-lisp можно написать
(defclass thing ()
((x :initarg :x :accessor thing-x)
(y :initarg :y :accessor thing-y)))
;; create foo of class thing with values (x=0,y=1)
(setq foo (make-instance 'thing :x 0 :y 1))
;; access attributes x and y in the scope defined by with-slots as
;; local variables and increment them
(with-slots (x y) foo
(incf x) (incf y))
;; now foo has values (x=1,y=2)
Теперь в Python3 я реализовал математическую модель, в которой я создаю словарь переменных и других компонентов.Если затем мне нужно написать некоторые математические выражения с этими переменными, после создания модели я должен написать что-то вроде
model.expr1 = model.var1 + data.coef2 * model.var2 ....
, но, конечно, var1...varn
имеют более длинные описательные имена.
Чтобы улучшить читабельность, я хотел бы иметь что-то
with ModelSlots(model) as (var1, var2, ... varn):
model.expr1 = var1 + data.coef2 * var2 ...
...
Насколько я понимаю, каждый менеджер контекста возвращает только один объект, поэтому решение, описанное выше, не должно быть возможным.
Есть ли у вас какие-либо идеи о том, как реализовать это в Python?
Конечно, очевидным решением было бы сделать
var1 = model.var1
var2 = model.var2
...
, но это долго, трудно читать, далеезагромождает контекст и может также привести к неясным ошибкам, поскольку я могу случайно оставить некоторые локальные var
переменные инициализированными к неправильному значению.
Наличие нескольких менеджеров контекста для каждой переменной
with Var1(model) as var1:
with Var2(model) as var2:
...
также не является решением, так как у меня может быть несколько переменных для использования в одной и той же области, и я могу захотеть быстро изменить или добавить новые.Необходимость определения диспетчера контекста для каждого из них была бы слишком громоздкой.
TIA
EDIT1
Комментировать решение Felix.Порядок / совпадение слотов может быть решен следующим образом:
from bunch import Bunch
class ModelSlots:
def __init__(self, model, *slots):
self._model = model
self._slots = list(map(lambda x: getattr(model,x), slots))
def __enter__(self):
return self._slots
def __exit__(self, *args):
pass
if __name__ == '__main__':
model = Bunch()
model.foo = 1
model.bar = 2
with ModelSlots(model, "bar", "foo") as (bar,foo):
print((foo, bar))
# prints (1,2)
Но тогда вам нужно повторить название слотов дважды, с кавычками и без них ...