如果需要第一个函数,如何在脚本中执行第二个函数?
Posted
技术标签:
【中文标题】如果需要第一个函数,如何在脚本中执行第二个函数?【英文标题】:How do you execute the second function in a script if it needs the first function? 【发布时间】:2017-07-20 18:19:42 【问题描述】:我认为这是基本的,我已经看到了我所问问题的多个版本,尽管它们都不完全是我所面临的。
我目前有一个包含两个函数的脚本,我希望能够只调用第二个函数,但它需要运行第一个函数。我的脚本仍然很乱,所以我使用了一个示例:
def func1(input): # Does something with input data
my_list = []
for i in input:
my_list.append(i)
return my_list # Returns a list
func1_list = func1(x) # Save the result from func1 into a variable
def func2(func1_list):
my_final_list = [] # This function just edits the first list
for val in my_list: # Results from func2 are needed later on
temp = val**3
my_final_list.append(temp)
return my_final_list
有没有办法在导入脚本时执行第二个函数而不必调用第一个函数?我不知道在哪里输入 func2 中的 func1_list 变量,这样任何人都可以直接进入 func2 并运行它(无论如何它都会自动执行 func1)。
编辑: func1 和 func2 都应该能够单独执行 - func2 依赖于 func1。两者都将显示信息(func2 仅显示修改后的信息)。示例:func1 将运行一些输入并显示原始结果,而 func2 将获取该原始结果并对其进行修改。如果需要,我希望能够查看原始结果和修改后的结果。
【问题讨论】:
从代码的模块范围中删除func1_list = func1(x)
,然后您可以在不调用func1
的情况下导入。
在调用func2
之前编写一个执行func1_list = func1(x)
的包装器?
函数是闭包,因此您可以简单地从函数中删除func1_list
参数(并将for val in my_list
更改为for val in func1_list
,或者更好:return [val**3 for val in func1_list]
。或者您可以使func2
致电func1
。
我认为你需要退后一步,解释一下你真正想要做什么。这个问题本身并没有多大意义,而且很难理解您要解决的基本问题是什么。
可以肯定的是,如果你最终打电话给func2
,my_list
会给出一个NameError
【参考方案1】:
如果您希望func1_list = func1(x)
仅在直接执行您的脚本时调用,您需要稍微修改您的脚本,以便在从模块调用时忽略它。您将使用这样的 if 条件:
if __name__ == '__main__':
func1_list = func1(x) # Save the result from func1 into a variable
__name__
仅在直接调用脚本时才等于__main__
,因此从模块调用时不会执行。
有关其工作原理的详细说明,请查看here。
【讨论】:
哦,我听说过这个,从来没有真正理解过。但是当你说它被直接调用时是什么意思呢?我导入了我的脚本,所以不是直接调用它吗?我也只是尝试将变量放在函数中,这似乎可行,但我不确定这是否是最佳做法。 如果文件名为A.py
,则运行python A.py
将导致该行执行。但是在B.py
中执行import A
不会。
@DNAngel 看官方docs。没有比这更正式的了。
哦,好吧,我将不得不解决这个问题。我对如何让我的 func2 在 func1 中使用相同的对象感到困惑,以便它可以在相同的数据集上工作。即 def func2(input)
@DNAngel 在 if 条件中,调用 func2(func1_list)
。另外,如果这个答案有帮助,您可以接受它(点击灰色复选标记)。【参考方案2】:
如果您尝试导入脚本,则必须遵循最佳实践和约定。
在不开始构建完整包的情况下,您至少需要确保不执行导入模块时未请求的代码。
要么将代码包装到 class
中,要么从模块的根目录中删除函数调用并提供必须调用的 init_function()
以准备环境。
使用 init_function() 并不丢人,很多库都这样做。
但是,我建议您在 Python classes 内构建您的代码。 FunctionsManager.py
示例:
class FunctionsManager:
def __init__(self):
self.func1_list = self.func1(x) # Save the result from func1 into a variable
def func1(self, input): # Does something with input data
my_list = []
for i in input:
my_list.append(i)
return my_list # Returns a list
def func2(self, func1_list):
my_final_list = [] # This function just edits the first list
for val in my_list: # Results from func2 are needed later on
temp = val**3
my_final_list.append(temp)
return my_final_list
然后在你的主代码中:
from FunctionsManager import FunctionsManager
manager = FunctionsManager() # Calls __init__() and so func1()
result = manager.func2(yourlist)
【讨论】:
感谢您提供的信息。上课总是让我害怕(笑),但我确实想按照最佳实践学习。我是一个完全没有课程的菜鸟,但我会再次阅读它并尝试相应地编辑我的函数!没有冒险,没有收获! 是的,我在这条道路上对你的所有鼓励 :-) 你会发现它比预期的要容易!享受 Python【参考方案3】:注意,您的问题基本上是在询问dependency injection 的入门知识。您可能会很好地阅读它。它与语言无关——它适用于 Java 和 Python 一样好。
您可以采取几种不同的方法;最佳选择取决于您的需求以及所涉及的功能的作用(这就是我在评论中提出所有问题的原因)。
您正在寻找的最简单的形式是让一个函数调用另一个函数。 (COLDSPEED 提到了这一点。):
def func1(input):
# do some magic to my_list with input
return my_list
def func2(input):
func1_list = func1(input)
# do some magic to make func2's my_list
return my_list
在这种情况下,func1 和 func2 都可以被调用。导入代码不必担心在 func2 之前调用 func1 - 这由 func2 负责。
在我讨论您的其他选择之前,您提到这两个函数都输出信息。将计算与输出分开是一种很好的做法。所以,不要这样做:
def func1(input):
# do some magic to my_list with input
print("func1: Stuff from my list...")
return my_list
def func2(input):
func1_list = func1(input)
print("func2: Stuff from my list...")
# do some magic to make func2's my_list
return my_list
因为调用func2
会打印出“func1”行和“func2”行。相反,将逻辑与输出分开。它可能看起来更复杂,但它为您提供了更多的构建块:
def func1(input):
# do some magic to my_list with input
return my_list
def func2(input):
func1_list = func1(input)
# do some magic to make func2's my_list
return my_list
def output_func1(input):
func1_list = func1(input)
print("func1_list stuff")
def output_func2(input):
func2_list = func2(input)
print("func2_list stuff")
现在你有很多不会产生很多噪音的可重用函数。
这是一个很好的步骤,您可以轻松使用它。如果func1
需要一个小时才能运行会发生什么?如果它已经运行过,您不想再次运行它。然后你想使用模块变量来保存状态。像这样的:
func1_results = None
def func1(input):
# do some magic to my_list with input
func1_results = my_list
return my_list
def func2(input):
if not func1_results:
func1(input) # this will only run if func1 hasn't been called yet
# do some magic to make func2's my_list
return my_list # you could similarly make a construct to save these results
现在,只有在需要时才会调用其依赖项的代码。我们越来越好。但是我们将输入传递给 func2,我们只在 func1 中关心它。您可以创建一个 func1 引用的模块变量input
,并且您的导入代码可以在调用任何函数之前设置它:
input = None
def func1():
# do some magic to my_list with module variable input
并将其调用为:
import my_funcs
my_funcs.input = "Happy happy input!"
my_funcs.func1() # or just my_funcs.func2(), etc.
这可能很好,但很危险——如果导入代码没有设置input
怎么办?解决这个问题的方法是 Fabien 提到的关于开设课程的内容:
class FuncRunner(object):
def __init__(self, input):
self.input = input
self.func1_results = None
def func1(self):
# do some magic to local my_list with input
self.func1_results = my_list
return my_list
def func2(self):
if not self.func1_results:
self.func1()
# do some magic to make func2's my_list
# maybe save the result as self.func2_results ?
return my_list
这将被调用为:
from my_funcs import FuncRunner
runner = FuncRunner("Happy happy input!")
foo = runner.func1() # or foo = runner.func2(), as per your needs
这样做的好处是不让你在不构造对象的情况下运行函数,而且__init__
的结构方式,如果不传递input
,就无法创建对象。 func1
找到的结果存储在对象中,因此它们始终关联在一起。在你的情况下,这可能是做你想做的最干净的方式。
【讨论】:
以上是关于如果需要第一个函数,如何在脚本中执行第二个函数?的主要内容,如果未能解决你的问题,请参考以下文章