Ответ 1
Лучшим подходом к выполнению этого будет использование декораторов, для этого у вас есть два варианта:
Декоратор на основе функций:
Вы можете создать декоратор на основе функций, который принимает в качестве аргумента представление латекса и прикрепляет его к функции, которую он украшает:
def latex_repr(r):
def wrapper(f):
f.latex = r
return f
return wrapper
Затем вы можете использовать его при определении своей функции и предоставить соответствующее представление:
@latex_repr(r'$ax^2 + bx + c$')
def func(x, a, b, c):
return a*x**2 + b*x + c
Это означает:
func = latex_repr(r'$ax^2 + bx + c$')(func)
и делает атрибут latex
доступным сразу после определения функции:
print(func.latex)
'$ax^2 + bx + c$'
Я представил представление как обязательный аргумент, вы можете определить разумное значение по умолчанию, если вы не хотите, чтобы представление всегда предоставлялось.
Декоратор на основе классов:
Если классы являются вашими предпочтениями, декоратор класса может также использоваться для аналогичного эффекта на более Pythonic пути, чем ваша первоначальная попытка:
class LatexRepr:
def __init__(self, r):
self.latex = r
def __call__(self, f):
f.latex = self.latex
return f
вы используете его таким же образом:
@LatexRepr(r'$ax^2 + bx + c$')
def func(x, a, b, c):
return a*x**2 + b*x + c
print(func.latex)
'$ax^2 + bx + c$'
Здесь LatexRepr(r'$ax^2 + bx + c$')
инициализирует класс и возвращает вызываемый экземпляр (__call__
). Что это делает:
func = LatexRepr(r'$ax^2 + bx + c$')(func)
# __init__
# __call__
и делает то же самое wrapped
.
Поскольку они оба просто добавляют аргумент функции, они просто возвращают его как-есть. Они не заменяют его другим вызываемым.
Хотя подход на основе классов делает трюк, декоратор на основе функций должен быть более быстрым и легким.
Вы дополнительно спросили:
", потому что Python" ленив "при выполнении функций": Python просто компилирует тело функции, он не выполняет никаких утверждений внутри него. Вот почему вам сначала нужно вызвать функцию для "получения" атрибута latex
.
Дополнительным недостатком этого подхода является то, что вы выполняете это назначение каждый раз, когда вы вызываете функцию