简体   繁体   English

Python:给定两个预制函数,如何有效选择要使用的函数?

[英]Python: how to efficiently choose which function to use, given two pre-made functions?

Let us say I have a module myfunctions with two functions: 假设我有一个带有两个功能的模块myfunctions

def functionA():
    return'Function A chosen.'

def functionB():
    return 'Function B chosen.'

Then, I have a module silly which does something with these functions: 然后,我有了一个silly的模块,它可以使用以下功能:

def sillyprinter():
    print chosen_function
    print chosen_function()

Then, In my main script, I have: 然后,在我的主脚本中,我有:

import myfunctions
import silly

class FunctionChooser():
    def __init__(function_choice="A"):
        self.choose_function_given_choice(function_choice)

    def do_something_many_times(self):
        for i in range(1000):
            silly.sillyprinter()

The idea of FunctionChooser is that it is initialized with some user given information regarding which function (A or B) I want to use from myfunctions . FunctionChooser的想法是使用一些用户初始化的信息,该信息提供了有关我想从myfunctions使用哪个功能(A或B)的myfunctions Then, after this choice is made, the user can call do_something_many_times , which makes use of yet another module, which will use the chosen function from myfunctions many times. 然后,在做出此选择之后,用户可以调用do_something_many_times ,它使用了另一个模块,该模块将多次使用myfunctions选择的功能。

In order to be efficient, I'd like to avoid the following: 为了提高效率,我想避免以下情况:

1) Choosing which function to use again and again -- so I'd like to make the choice once (during initialization), and then have it "saved" somehow. 1)选择一次又一次使用哪个函数-所以我想一次选择(在初始化期间),然后以某种方式“保存”。 This requirement disqualifies designs like: 该要求取消了以下设计的资格:

def sillyprinter(chosen_function):
    print chosen_function
    print chosen_function()

# =================================

class FunctionChooser():
    def __init__(function_choice="A"):
        self.function_choice = function_choice

    def choose_function_given_choice(self):
        if self.function_choice == "A":
            return myfunctions.functionA
        elif self.function_choice == "B":
            return myfunctions.functionB

    def do_something_many_times(self):
        for i in range(1000):
            silly.silly_printer(self.choose_function_given_choice())

2) storing the function I'd like to choose as a class attribute, since self calls are expensive, and the use case is numerical . 2)存储我想选择的函数作为类属性, 因为self调用很昂贵,用例是数字 This requirements disqualifies designs like: 此要求取消了以下设计的资格:

def sillyprinter(chosen_function):
    print chosen_function
    print chosen_function()

# =================================

class FunctionChooser():
    def __init__(function_choice="A"):
        self.function_choice = function_choice

    def choose_function_given_choice(self):
        if self.function_choice == "A":
            self.chosen_function = myfunctions.functionA
        elif self.function_choice == "B":
            self.chosen_function = myfunctions.functionB

    def do_something_many_times(self):
        for i in range(1000):
            silly.silly_printer(self.chosen_function)

My current idea is to do the following: 我当前的想法是执行以下操作:

def sillyprinter(chosen_function):
    print chosen_function
    print chosen_function()

# =================================

class FunctionChooser():
    def __init__(function_choice="A"):
        self.function_choice = function_choice

    def choose_function_given_choice(self):
        if self.function_choice == "A":
            self.chosen_function = myfunctions.functionA
        elif self.function_choice == "B":
            self.chosen_function = myfunctions.functionB

    def do_something_many_times(self):
        chosen_function = self.chosen_function
        for i in range(1000):
            silly.silly_printer(chosen_function)

It is only very slightly different than the design I disqualified in 2) , in that it makes a self call once and then stores that function for use as a local variable. 它与我在2)中取消资格的设计仅略有不同,因为它会进行一次self调用,然后将该函数存储为局部变量。

Is this the best way to design such "function choice" in Python, given my requirements? 根据我的要求,这是在Python中设计此类“函数选择”的最佳方法吗? (see below) (见下文)

EDIT: I figure I should make requirements clearer, in order to make the question less general 编辑:我认为我应该使要求更明确,以使问题不太普遍

  1. The "function choice string" does not have to be a string -- it could be any variable that encodes for some sort of function choice. “函数选择字符串”不必是字符串,它可以是为某种函数选择编码的任何变量。
  2. I want to avoid self. 我想避免self. access calls (but perhaps . access calls in general?) due to issues with numba optimizing code with access calls: Design heuristics for writing Python classes that interact with `scipy.integrate.odeint`? 访问调用(但一般来说可能是.访问调用?)是由于numba使用访问调用优化代码的问题所致: 设计试探法来编写与`scipy.integrate.odeint'交互的Python类。
  3. The "function choice" variable is only given once, so we can consider it to effectively be a constant. “功能选择”变量仅给出一次,因此我们可以认为它实际上是一个常数。

No. Functions in Python are first-class objects; 否。Python中的函数是一流的对象。 treat them as such. 这样对待他们。

class FunctionChooser():
    def __init__(function_choice=myfunctions.functionA):
        self.function_choice = function_choice

    def do_something_many_times(self):
        chosen_function = self.chosen_function
        printer = silly.silly_printer
        for i in range(1000):
            printer(chosen_function)

The fundamental answer is that any of these three options may be the "best," depending on circumstances. 基本的答案是, 根据情况,这三个选项中的任何一个都是 “最佳”的。 But the differences between the options you've chosen are subtle, and not likely to affect performance significantly most of the time. 但是,您选择的选项之间的差异是细微的,并且在大多数情况下不太可能显着影响性能。 Instead of worrying about efficiency here, you should worry about conceptual elegance. 在这里不必担心效率,而应该担心概念上的优雅。 Then, if you need efficiency, optimize. 然后,如果您需要效率,请进行优化。

I could imagine situations when any of these three options would be preferable, conceptually. 从概念上讲,我可以想象这三个选项中的任何一个都更可取的情况。

  1. Suppose the choice of function will depend on a value that changes frequently. 假设功能的选择将取决于经常变化的值。 You'll have to check its state frequently, so what will you gain by storing it? 您将不得不经常检查其状态,那么通过存储它会得到什么呢? It makes more sense simply to look it up every time. 每次都查找它更有意义。 In this case, (1) is the best option. 在这种情况下,(1)是最佳选择。

  2. Suppose the choice of function won't be based on a value that changes often, or that is easy to "invert control" with (ie the code that pays attention to the variable knows to change the function selection as well). 假设函数的选择将不会基于经常更改的值,也不会基于易于“反转控制”的值(即,关注变量的代码也知道会更改函数的选择)。 Unless you have an overriding reason to worry about the extra overhead of a single . 除非您有压倒一切的理由担心单个服务器的额外开销. access, just store this as an attribute. 访问,只需将其存储为属性即可。 (And note that looking up an attribute in self is no more costly than looking up an attribute in some other object. The operation is exactly the same; there's nothing special about self !) In this case, (2) is the best option. (请注意,在self中查找属性并不比在其他对象中查找属性昂贵。操作完全相同; self没什么特别的!)在这种情况下,(2)是最佳选择。

  3. Suppose, as you have, that the choice of function won't be based on a value that changes often, but that the function will itself be called frequently. 如您所愿,假设函数的选择不会基于经常更改的值,而是函数本身会被频繁调用。 Furthermore, you are certain that the . 此外, 您可以确定 . access is slowing down your code, because you have done rigorous tests . 访问已使您的代码变慢,因为您已经执行了严格的测试 Then it makes sense to cache the result of the . 然后就可以缓存的结果了. access in a local variable, as in option (3). 访问局部变量,如选项(3)所示。 (But note that in option (3) you're still using another . operation -- that should be cached as well, as in Ignacio's answer.) But beware premature optimization! (但是请注意,在选项(3)中,您仍在使用另一个.操作-也应将其缓存,就像在Ignacio的答案中一样。)但是要提防过早的优化! Every local variable imposes an additional cognitive load on you and your fellow developers -- you must be sure it's worth it. 每个局部变量都会给您和您的开发人员带来额外的认知负担-您必须确保这样做是值得的。 Only choose this option if you've actually done tests, and it makes a significant speed difference. 当您实际完成测试后才选择此选项,这会显着提高速度。

A final note: there's also some extra complexity in your example code that I am assuming is supposed to be evocative of complexity rather than specifically purposeful in this particular case. 最后一点:在您的示例代码中还存在一些额外的复杂性,我认为这应该引起复杂性,而不是在这种特殊情况下特别有目的。 For example, given the code you've actually posted, the choose_function_given_choice function is quite useless. 例如,考虑到您实际发布的代码, choose_function_given_choice函数是完全没有用的。 But I think you know that already. 但是我想你已经知道了。 Still, to restate the obvious -- you should make all of this happen in the simplest way possible. 尽管如此,重申一下显而易见的事实-您应该以最简单的方式实现所有这些目标。

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

相关问题 如何在项目中使用预制应用程序? - How do I use a pre-made app with my project? 如何读取用户的输入,搜索预先制作的字符串列表,然后在 Python 中返回匹配的内容? - How to read the user's input, searching for a pre-made list of strings, and then return the matched content in Python? 如何在matplotlib中为热图使用预制的颜色贴图? - How can I use a pre-made color map for my heat map in matplotlib? 为 TensorFlow 预制估计器定义输入函数 - Defining the input-function for TensorFlow pre-made estimator 1.14版中的预制估算器的推断输入函数 - input function for inference with pre-made Estimator in version 1.14 如何将名称列表实现为预制类? - How to implement list of names into a pre-made class? 如何在 tensorflow 2.0 中使用预制密集层进行训练? - How to run training with pre-made dense layers in tensorflow 2.0? 使用预制用户界面 (pygubu) 时如何在 Tkinter 中扩展滚动条 - How to expand a Scrollbar in Tkinter when working with a pre-made user interface (pygubu) 将两个给定函数应用于Python中外部参数的函数 - Function that applies two given functions to an outside argument in Python 程序如何在python中选择两个函数? - How can the program choose between two function in python?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM