简体   繁体   English

如果需要第一个功能,如何在脚本中执行第二个功能?

[英]How do you execute the second function in a script if it needs the first function?

I think this is basic and I've seen multiple versions of the question I am asking although they are all not exactly what I am facing. 我认为这是基本知识,尽管我所面对的问题并不完全是我遇到的问题的多个版本。

I have a script with two functions currently, and I want the ability to evoke just the second function but it needs to run the first function. 我目前有一个具有两个功能的脚本,我希望能够仅调用第二个功能,但它需要运行第一个功能。 My script is still messy so I am using an example: 我的脚本仍然很混乱,因此我使用一个示例:

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

Is there a way to execute the second function without having to call the first function when importing a script? 有没有一种方法可以在导入脚本时执行第二个功能而不必调用第一个功能? I have no clue where to input the func1_list variable in func2 so that anyone can just go straight to func2 and run it (and it will automatically execute func1 anyways). 我不知道在哪里在func2中输入func1_list变量,这样任何人都可以直接进入func2并运行它(无论如何它将自动执行func1)。

EDIT: Both func1 and func2 should be able to be executed individually - func2 relies on func1. 编辑:func1和func2都应该能够单独执行-func2依赖于func1。 Both will show information (func2 just showing modified information). 两者都将显示信息(func2仅显示修改后的信息)。 Example: func1 will run some input and show the raw result, whereas func2 will take that raw result and modify it. 示例:func1将运行一些输入并显示原始结果,而func2将获取该原始结果并对其进行修改。 I'd want the ability to see the raw and modified result if needed. 如果需要,我希望能够查看原始结果和修改后的结果。

If you want func1_list = func1(x) to only invoke when directly executing your script, you'll need to modify your script a bit so it is ignored when called from a module. 如果希望func1_list = func1(x)仅在直接执行脚本时才调用,则需要对脚本进行一些修改,以便从模块调用时将其忽略。 You'll use an if condition like this: 您将使用以下if条件:

if __name__ == '__main__':
    func1_list = func1(x) # Save the result from func1 into a variable

__name__ equals __main__ only when the script is invoked directly, so it will not execute when called from a module. 仅在直接调用脚本时, __name__等于__main__ ,因此从模块调用脚本时,它不会执行。


For a detailed description of how it works, look here . 有关其工作原理的详细说明,请参见此处

If you are trying to import your script, you must follow the best practices and conventions. 如果要导入脚本,则必须遵循最佳实践和约定。

Without starting to build a full-package, you need to, at least, ensure that you do not execute code that is not requested when importing the module. 在不开始构建完整程序包的情况下,至少需要确保您不执行导入模块时不要求的代码。

Either you wrap your code into a class , or you remove function calls from within the root of your module and you provided an init_function() which must be called to prepare the environment. 您可以将代码包装到一个class ,或者从模块根目录中删除函数调用,然后提供一个init_function()来准备环境。

There is no shame in using an init_function() and a lot of libraries do that. 使用init_function()没有什么可耻的,很多库都这样做。

However, I recommend that you structure your code within Python classes . 但是,我建议您在Python类中构建代码。 Example of FunctionsManager.py : 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

And then in your main code: 然后在您的主要代码中:

from FunctionsManager import FunctionsManager

manager = FunctionsManager() # Calls __init__() and so func1()
result = manager.func2(yourlist)

Note, your question is basically asking for a primer on dependency injection . 请注意,您的问题基本上是寻求有关依赖注入的入门。 You would probably do well to read up on it. 您可能会做得很好,继续阅读。 It's language-agnostic - it applies as nicely to Java as it does to Python. 它与语言无关-与Python一样适用于Java。

There are several different approaches you can take for this; 您可以采用几种不同的方法。 the best choice depends on your needs and what the functions involved do (which is why I was asking all the questions in the comment). 最佳选择取决于您的需求以及所涉及的功能(这就是为什么我在评论中问所有问题)的原因。

The simplest form of what you're looking for is to just have one function invoke the other. 您要查找的最简单形式是让一个函数调用另一个函数。 (COLDSPEED made reference to this.): (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

In that case, func1 and func2 are both able to be called. 在这种情况下,func1和func2都可以被调用。 The importing code doesn't have to worry about calling func1 before func2 - that's taken care of by func2. 导入代码不必担心在func2之前调用func1,这由func2负责。

Before I get into your other choices, you mentioned that both functions output information. 在我做出其他选择之前,您提到过这两个函数都输出信息。 It's a good practice to separate your calculations from your output of them. 将您的计算与输出分开是一个好习惯。 So, DON'T do this: 因此, 请勿这样做:

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

Because then calling func2 would print out the "func1" line and the "func2" line. 因为然后调用func2会打印出“ func1”行和“ func2”行。 Instead, separate the logic from the output. 而是将逻辑与输出分开。 It may seem more complicated, but it gives you more building blocks to play with: 它可能看起来更复杂,但是它为您提供了更多的构建基块:

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")

Now you have a lot of reusable functions that don't generate a lot of noise. 现在,您有许多可重复使用的功能,不会产生很多噪音。

This is a good step, and you can use this easily. 这是一个好步骤,您可以轻松地使用它。 What happens if func1 takes an hour to run? 如果func1运行一个小时会发生什么? You don't want to run it again if it's already been run. 如果已经运行过,则您不想再次运行它。 Then you want to use module variables to save state. 然后,您想使用模块变量来保存状态。 Something like this: 像这样:

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   

Now you get code calling its dependencies only if it needs to. 现在,仅在需要时,您才能获得调用其依赖项的代码。 We're getting better. 我们越来越好了。 But we're passing input into func2, and we only care about it in func1. 但是我们将输入传递给func2,我们只在func1中关心它。 You could make a module variable input that func1 refers to, and your importing code could set it before calling any of the funcs: 您可以input func1所引用的模块变量input ,并且您的导入代码可以在调用任何函数之前对其进行设置:

input = None
def func1():
    # do some magic to my_list with module variable input

And invoke it as: 并将其调用为:

import my_funcs
my_funcs.input = "Happy happy input!"
my_funcs.func1() # or just my_funcs.func2(), etc.

This could be nice, but it's dangerous - what if the importing code doesn't set input ? 这可能很好,但是很危险-如果导入代码未设置input怎么办? The solution to that is what Fabien mentioned about having a class: 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

This would be invoked as: 这将被调用为:

from my_funcs import FuncRunner
runner = FuncRunner("Happy happy input!")
foo = runner.func1()  # or foo = runner.func2(), as per your needs

This does the nice thing of not letting you run functions without constructing the object, and the way the __init__ is structured, you can't create the object without passing input . 这样做的好处是不允许您在不构造对象的情况下运行函数,并且__init__的结构方式是,您必须在不传递input情况下创建对象。 The results found by func1 are stored within the object, so they're always associated together. func1找到的结果存储在对象中,因此它们始终关联在一起。 In your case, this is likely the cleanest way to do what you want. 就您而言,这可能是您要做的最干净的方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM