如何将脚本划分为较小的脚本和模块并连接到工作区变量?
我在Jupyter的Python中启动了会议,并为与之合作的应用程序提供了部分量身定制的脚本。该脚本既包含依赖应用程序的字典和函数,又包含某些功能。我想制作一个通用模块,并使启动脚本仅包含应用程序部分。困难是我希望通用模块中的函数将应用程序词典作为默认值。那么如何将此类工作空间词典连接到导入的功能?
下面一个非常简单的示例说明了问题。首先,您看到原始的总启动脚本。这是有效的。
import numpy as np
import matplotlib.pyplot as plt
parDict = {}
parDict['Y'] = 0.5
parDict['qSmax'] = 1.0
parDict['Ks'] = 0.1
def par(parDict=parDict, *x, **x_kwarg):
""" Set parameter values if available in the predefined dictionaryt parDict. """
x_kwarg.update(*x)
x_temp = {}
for key in x_kwarg.keys():
if key in parDict.keys():
x_temp.update({key: x_kwarg[key]})
else:
print(key, 'seems not an accessible parameter')
parDict.update(x_temp)
而且我可以在笔记本中给出par(y = 0.4)之类的命令,然后检查词典中的结果。
第二(下图)您会看到将一般函数分解为模块的尝试,并且该功能在启动脚本中导入。在实际模块下方。此代码不起作用。错误消息是:未定义的名称'pardict' 如何修复它?
parDict = {}
parDict['Y'] = 0.5
parDict['qSmax'] = 1.0
parDict['Ks'] = 0.1
from test_module import par
and test_module.py
def par(parDict=parDict, *x, **x_kwarg):
""" Set parameter values if available in the predefined dictionaryt parDict. """
x_kwarg.update(*x)
x_temp = {}
for key in x_kwarg.keys():
if key in parDict.keys():
x_temp.update({key: x_kwarg[key]})
else:
print(key, 'seems not an accessible parameter')
parDict.update(x_temp)
如果我在函数中取出默认参数,则可以正常工作,但是我必须有一个更长的呼叫,例如par(pardict,y = 0.4)。我想避免这个冗长的通话,并自动提供默认的贫困。一个想法是在启动脚本中从导入的函数中产生一个新功能,并在这里与字典建立连接。但是似乎是笨拙的方法,还是唯一的选择?
I start up sessions in Jupyter with Python with a partly tailor-made script for the application I work with. The script contains both application dependent dictionaries and functions, but some function are of a general kind. I would like to make a general module and make the start-up script contain only application parts. The difficulty is that I want the functions in the general module have application dictionaries as default. So how to connect such workspace dictionaries to the imported functions?
A very simplifed example below illustrate the problem. First you see the original total startup script. This codes works.
import numpy as np
import matplotlib.pyplot as plt
parDict = {}
parDict['Y'] = 0.5
parDict['qSmax'] = 1.0
parDict['Ks'] = 0.1
def par(parDict=parDict, *x, **x_kwarg):
""" Set parameter values if available in the predefined dictionaryt parDict. """
x_kwarg.update(*x)
x_temp = {}
for key in x_kwarg.keys():
if key in parDict.keys():
x_temp.update({key: x_kwarg[key]})
else:
print(key, 'seems not an accessible parameter')
parDict.update(x_temp)
And I can in the notebook give a command like par(Y=0.4) and then inspect the results in the dictionary parDict.
Second (below) you see an attempt to break out the general functions into a module and this functions are imported in the start-up script. And below the actual module. This code does not work. The error message is: name 'parDict' is not defined
How to fix it?
parDict = {}
parDict['Y'] = 0.5
parDict['qSmax'] = 1.0
parDict['Ks'] = 0.1
from test_module import par
And test_module.py
def par(parDict=parDict, *x, **x_kwarg):
""" Set parameter values if available in the predefined dictionaryt parDict. """
x_kwarg.update(*x)
x_temp = {}
for key in x_kwarg.keys():
if key in parDict.keys():
x_temp.update({key: x_kwarg[key]})
else:
print(key, 'seems not an accessible parameter')
parDict.update(x_temp)
If I in the function take away the default argument parDict then it works, but I must then have a lengthier call like par(parDict, Y=0.4). I would like avoid this lengthy call and provide the default parDict automatically. One idea is to in the start-up script make a new function from the imported function and here make the connection to the dictionary. But seems a clumsy way to do it, or the only choice?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
在您尝试定义函数
par
字典pardict
的地方不确定。您可以将pardict
的定义移至test_module.py
(在函数定义之前)。附带说明,请注意Python中可变违约论点的危险:
https://docs.pys.python-guide.orgg/writing/gotchas/gotchas/gotchas/gotchas /#Mutable-default-arguments
它们会导致意外行为。
我的建议:
然后这样打电话:
At the place where you try to define the function
par
the dictionaryparDict
is undefined. You could move the definition ofparDict
intotest_module.py
(before the function definition).As a side note, please be aware of the dangers of mutable default arguments in Python:
https://docs.python-guide.org/writing/gotchas/#mutable-default-arguments
They can cause unexpected behavior.
My suggestion:
Then call like this:
我上面概述的暂定解决方案的细节看起来像这样。关键想法是在启动脚本中导入模块的函数parx(),然后制作一个新函数par(),其中pardict是默认参数,从而在此级别上“连接”到该级别的函数,而在模块级别不起作用。因此,在启动脚本中,词典暂停是隐式函数PAR()可以操作的全局变量。
调整后的test_module2.py是:
首先测试表明它有效。通过这种方式,我避免将贫困作为默认参数引入,而只是将其作为全局变量访问。因此,避免了在上面链接中评估默认参数何时评估的不确定性。此代码是否有任何问题?
建议这样做更好的方法?
通常,我想避免使用全局变量并将它们引入它们,因为默认参数可提高可读性,但是它可能会像上面的链接所解释的那样引入问题,而我删除了这个想法。我要使用诸如Pardict之类的工作区词典作为全局变量的原因是具有非常短的命令行函数,例如:par(),...以使用其内容来管理词典。工作区词典的名称始终相同,但内容取决于应用程序。在词典上运行的PAR()诸如PAR()之类的一般功能需要逐步更新,扩展等等,并且可以从模块中心进行中心,而不是从每个单独的启动脚本中进行。
The details of the tentative solution I sketched above look like this. The key idea is to in the start-up script import the function parX() from the module, but then make a new function par() where parDict is default parameter and thus "connected" to the function at this level, while at the module level it does not work to do this connection. Thus in the start-up script the dictionary parDict is implicitly a global variable that the function par() can operator on.
and adjusted test_module2.py is:
First tests show that it works. In this way I avoid introducing parDict as a default parameter, and simply access it as a global variable. So uncertainty of when default parameters are evaluated discussed in a link above is avoided. Can here be any problems with this code?
Suggestions for better ways to do this?
Generally I want to avoid using global variable and introducing them instead as default parameters improve readability, but it may introduce problems as the link above explains, and I dropped that idea. The reason I want to use workspace dictionaries like parDict as global variables is to have very short command-line functions like: par(),... to administrate the dictionaries with and later operate on their content. The name of the workspace dictionaries are always the same but the content is application dependent. The general functions like par() that operate on the dictionaries need to be gradually updated, and extended etc, and good to do that centrally from a module, rather than from each individual start-up script.
现在我整理了一个更好的解决方案,我想与大家分享!关键是利用 Python 类概念,它可以将字典与相关功能结合起来,并从模块导入类。在导入类后,您可以在安装文件中使用应用程序参数名称和值填充字典,并为关联函数指定一个简短名称。如果您愿意,可以用“抽象数据类型”来描述。
启动脚本现在如下所示:
更新后的 test_module3 现在更加复杂:
最后,在 Jupyter 笔记本中,您现在可以像以前一样使用简化的命令行 par(Y=0.4, Ks=0.08) 更改 parDict 中的参数值) ETC。
Now I have put together an even better solution that I want to share with you! The key is to make use of Python class-concept that give the possibility to combine a dictionary with associated functionality and you import the class from a module. In the setup-file you then after import of the class populate the dictionary with application parameter names and value and you make a short name for the associated function. This could be described in terms of "abstract datatype" if you like.
The start-up script now look like this:
and the updated test_module3 is now somewhat more complex:
Finally out in the Jupyter notebook you can now change parmeter values in parDict as before with simplified command-line par(Y=0.4, Ks=0.08) etc.