【发布时间】:2021-08-20 00:18:19
【问题描述】:
我发现这个有用的装饰器允许你传入一些可选参数
def mlflow_experiment(
_func=None,
*,
experiment_name=None
):
def experiment_decorator(func):
@functools.wraps(func)
def experiment_wrapper(self, *args, **kwargs):
nonlocal experiment_name
experiment_id = (
mlflow.set_experiment(experiment_name)
if experiment_name is not None
else None
)
...
value = func(self, *args, **kwargs)
return value
return experiment_wrapper
if _func is None:
return experiment_decorator
else:
return experiment_decorator(_func)
因此,在这样的用例中,我只需将字符串传递给experiment_name,代码就可以完美运行。
@mlflow_experiment(autolog=True, experiment_name = 'blarg')
def train_mlflow(self, maxevals=50, model_id=0):
...
我一直很难确定装饰器的作用域,但我并不感到惊讶的是,使用传递 __init__ 中定义的实例变量不起作用。
class LGBOptimizerMlfow:
def __init__(self, arg):
self.arg = arg
@mlflow_experiment(autolog=True, experiment_name = self.arg)
def train_mlflow(self, maxevals=50, model_id=0):
...
>>> `NameError: name 'self' is not defined`
只是为了看看作用域是否存在问题,我在类之外声明了变量并且它起作用了。
为了它,我决定在类中声明一个全局变量,它也可以工作,但它不太理想,特别是如果我想将它作为可选参数传递给类或方法。
class LGBOptimizerMlfow:
global arg
arg = 'hi'
@mlflow_experiment(autolog=True, experiment_name = arg)
def train_mlflow(self, maxevals=50, model_id=0):
...
修改代码以使装饰器接受实例变量的任何帮助都会很可爱。
谢谢!
【问题讨论】:
-
你不能这样做,因为装饰器是在定义 class 时调用的,远在类的任何实例存在之前。
-
您省略了实际使用
experiment_name参数的装饰器部分,因此很难推荐一种解决方法。 -
@chepner,对此感到抱歉。我意识到我确实遗漏了它。我会重新编辑它。还发现了这个:stackoverflow.com/questions/11731136/…
标签: python python-3.x python-decorators python-descriptors