我发现了这个有用的装饰器,它允许您传入一些可选参数
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):
...
我一直很难理解decorators中的作用域,但使用传递在__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):
...
修改代码以使装饰器接受实例变量的任何帮助都将非常有用
谢谢大家!
在定义类时调用Decorators,而
self
只是用于每个实例方法的参数,而不是类本身提供的参数。因此self
在需要用作装饰器的参数时没有定义您需要修改
experiment_wrapper
以直接从其self
参数获取名称,而不是从参数获取mflow_experiment
。差不多然后,您需要确保每个实例都有一个与之关联的实验名称(或没有)
另一种选择是将
experiment_name
作为train_mflow
的参数,这样可以更容易地使用相同的方法创建不同的名称。(这可能更接近您的预期。)装饰器的定义与上面所示的相同
相关问题 更多 >
编程相关推荐