[英]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 编辑:我认为我应该使要求更明确,以使问题不太普遍
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类。 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. 从概念上讲,我可以想象这三个选项中的任何一个都更可取的情况。
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)是最佳选择。
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)是最佳选择。
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.