Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/278.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python exec()全局更新参数,但可以';在另一个函数中找不到_Python_Dictionary_Scope_Exec_Python 2.x - Fatal编程技术网

Python exec()全局更新参数,但可以';在另一个函数中找不到

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

所以我在使用python 2.7

我使用这一行执行字典中的一系列语句:

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)