Python exec()全局更新参数,但可以';在另一个函数中找不到
所以我在使用python 2.7 我使用这一行执行字典中的一系列语句:Python exec()全局更新参数,但可以';在另一个函数中找不到,python,dictionary,scope,exec,python-2.x,Python,Dictionary,Scope,Exec,Python 2.x,所以我在使用python 2.7 我使用这一行执行字典中的一系列语句: for key in pipeline: exec(dictionary[key], globals(), globals()) 这是管道包含的内容: pipeline = { 'initializer' : 'initializer()', 'preprocesser' : 'preprocesser()' } 以下是两个initializer()和preprocesser()函数: def
for key in pipeline:
exec(dictionary[key], globals(), globals())
这是管道包含的内容:
pipeline = {
'initializer' : 'initializer()',
'preprocesser' : 'preprocesser()'
}
以下是两个initializer()和preprocesser()函数:
def initializer():
global params
data = pd.read_csv(params['dataset'])
data.fillna(0, inplace=True)
params['data'] = data
return params
def preprocesser():
global params
print(params.keys())
这两个函数都修改了一个名为params的全局字典,如下所示:
params = {
'instruction' : "Predict median house value",
'dataset' : './data/housing.csv',
}
出于某种原因,如果我打印出params的dictionary键,它将打印更新的键:initializer()函数应该向全局params dictionary添加一个“data”键。但是如果我打印出preprocessor()函数中的键列表,我只会得到['instruction','dataset']。如果我在调用exec函数(在全局范围内)后立即打印出键,它会正确地打印出[‘指令’、‘数据集’、‘数据]。为什么它是全局更新的,但是我不能在preprocesser()函数中访问更新的参数。如何解决这个问题?在Python2.7中,dictionary对象不维护插入顺序。请遵守生成的顺序:
In [3]: pipeline = {
...: 'initializer' : 'initializer()',
...: 'preprocesser' : 'preprocesser()'
...: }
In [4]: list(pipeline)
Out[4]: ['preprocesser', 'initializer']
所以先运行预处理器。在这里,您根本不需要dict,您可以使用元组列表,或者如果出于其他原因,您的代码需要dict,那么您可以按照希望运行的顺序保留键列表
但总而言之,这整个方法是不可取的。这里不要使用exec
,它没有任何优势,动态代码执行有很多缺点,在这种情况下完全没有必要。在几乎所有的情况下,包括这一个,它都是一个明确的反模式
另外,不要使用可变全局状态。这是另一个众所周知的反模式。而是显式地将参数传递给函数。以下是我将如何做到这一点:
In [9]: def initializer(params):
...: params['data'] = 42
...: return params
...:
...: def preprocesser(params):
...: print(params.keys())
...:
In [10]: pipeline = [(initializer, (params,)), (preprocesser, (params,))]
In [11]: for func, args in pipeline:
...: func(*args)
...:
['instruction', 'data', 'dataset']
In [12]: params
Out[12]:
{'data': 42,
'dataset': './data/housing.csv',
'instruction': 'Predict median house value'}
现在,一般来说,函数改变其输入也被认为是一种反模式,但这应该会让你朝着更理智的方向发展
最后,您应该避免使用Python 2,它已经过了正式的生命周期,甚至不再获得安全更新,并且已经放弃了支持,包括您正在使用的
pandas
。仅适用于将来的任何人,如果您的参数是全局的,您还可以执行以下操作:
reg_pipeline = [initializer,
preprocesser]
for func in reg_pipeline:
func(init_params)