简体   繁体   English

在多次调用同一函数时重用数据的最pythonic方法是什么?

[英]What is the most pythonic way to reuse data in multiple calls to same function?

Normally I would not ask such a question, but python seems to have 1. an unusual level of community consensus on idioms and 2. tends to encourage them by making them more performant (eg list comprehension vs map, filter). 通常我不会问这样的问题,但是python似乎有1.一个不同寻常的社区对习语的共识,并且通过使它们更具性能来鼓励它们(例如列表理解与地图,过滤器)。

This is a pattern I find myself using quite a bit when coding, consider the following JavaScript: 这是我在编码时发现自己使用的模式,请考虑以下JavaScript:

var f = (function() {
  var closedOver = "whatever"
  return function(param) {
    // re-uses closure variable again and again with different param
  }
})();

Or C: 或者C:

int foo(int x)
{
  /* 
    compile-time constant, will not be recalced for every call,
    name 'someConst' not visible in other scopes 
  */
  const int someConst = 134;
  /* do stuff */
  return whatever;
}

Some possible ways to translate into python: 一些可能的方法转换为python:

globalConstant = someConstant
def foo(param):
    # does stuff with param and constant
    return whatever

or possibly: 或者可能:

from functools import partial
def foo(invariant, variant):
    """Actually bar"""
    # does stuff
    return whatever

bar = partial(foo, someInvariant)

or: 要么:

class Foo(object):
    """I'm just here to hold a non-visible binding. Actually bar"""
    def __init__(self, invariant):
        super(Foo, self).__init__()
        self.value = invariant

    def __call__(self, param):
        return actualFnResultWithSelfValue

bar = Foo(invariant)

or: 要么:

def foo(variant, invariant=someConstantValue):
  return whatever

This is unfortunate, now depending on which way I go I may have to use a throw-away name for the initial function definition since I'm only ever using the partially applied version, write a lot of boilerplate classes (which also have throw-away names), or pollute the module namespace with a global constant when its only used in one function, or restrict my function parameters and ensure that someone can break it by calling it with the wrong number of arguments. 这是不幸的,现在取决于我走哪条路我可能不得不使用一个丢弃的名称作为初始函数定义,因为我只使用部分应用的版本,写了很多样板类(也有抛出 - 当它仅在一个函数中使用时,或者使用全局常量污染模块命名空间,或限制我的函数参数并确保有人可以通过使用错误数量的参数调用它来破坏它。

I could also 'solve' this by re-instantiating on every call and hoping that it will get optimized away, but since I'm not using pypy I'm not too hopeful on that score. 我也可以通过重新实例化每次通话来“解决”这个问题,并希望它会被优化掉,但由于我没有使用pypy,我对这个得分并不太有希望。

So my question is two-fold: first, is there a way to do this without the trade-offs? 所以我的问题有两个方面:首先,有没有办法在没有权衡的情况下做到这一点? And second, if not, which of the above is the most 'pythonic' (idiomatic, performant, reasonable, etc.)? 第二,如果没有,上面哪个是最“pythonic”(惯用,高性能,合理等)?

Jared, I totally understand your hesitation to ask this, because it could be answered by many different opinions and spawn a flame war. 贾里德,我完全明白你犹豫要问这个,因为它可以通过许多不同的意见来回答,并产生一场火焰战争。 But, I do agree with your observation: the Python community does tend towards consistency over time with many implementation questions. 但是,我同意你的看法:随着时间的推移,Python社区确实倾向于与许多实现问题保持一致。 That's one of the strengths of Python. 这是Python的优势之一。

Here's my rule of thumb: When in doubt, try to use the Python standard library as much as possible. 这是我的经验法则:如有疑问,请尽量使用Python标准库。 Your instinct here about functools.partial is correct, for these reasons: 你对functools.partial直觉是正确的,原因如下:

  1. The Python standard library is highly optimized C code that will out-perform any Python class or function closure structure you come up with. Python标准库是高度优化的C代码,它将超出您提出的任何Python类或函数闭包结构。
  2. The Python standard library is widely used by other Python programmers, so when you use it, your coding intent will be more widely understood by other Python programmers. Python标准库被其他Python程序员广泛使用,因此当您使用它时,其他Python程序员将更广泛地理解您的编码意图。 ("Code is read more often than it is written.") (“代码的读取频率高于编写代码。”)
  3. The Python standard library is programmed by the core Python developers; Python标准库由核心Python开发人员编写; no code could possibly claim to be more "Pythonic" than the standard library. 没有代码可能声称比标准库更“Pythonic”。

I hope that helps! 我希望有所帮助!

I'd suggest something that's usually a code smell - default mutable argument. 我建议一些通常是代码气味的东西 - 默认的可变参数。

Trivial example: 琐碎的例子:

def f(x, cache={'x': 0}):
    cache['x'] += x;
    return cache['x']


assert f(1) == 1
assert f(1) == 2  
assert f(1) == 3
assert f(3) == 6

Your dict (or list, or anything which is mutable) is bound to function object. 您的dict(或列表,或任何可变的)绑定到函数对象。 Subsequent calls, when cache keyword argument is omitted, will refer to same object. 当省略cache关键字参数时,后续调用将引用同一对象。 This object state will persist across calls. 此对象状态将在调用之间保持不变。

I don't like idea with var in outer scope and may suggest use closure, I think it's better way, as you see it's more like JavaScript, so you can work with functions as objects : 我不喜欢外部范围的var的想法,可能建议使用闭包,我认为这是更好的方式,因为你看它更像JavaScript,所以你可以使用函数作为对象:

def foo():
    const = 1
    def bar(param):
      return const + param
    return bar

a = foo()
print(a(5))

There is an alternative that you didn't mention, which is IMO the most pythonic way which wouldn't create a throw away name :) 还有一个你没有提到的替代方案,这是IMO最狡猾的方式,它不会创造一个扔掉的名字:)

def foo(variant):
    try:
        return foo.invariant + variant
    except AttributeError:
        foo.invariant = 1
        return foo(variant)

Although, sticking with the std library would be the best. 虽然坚持使用std库是最好的。

I don't think your two first examples are equivalent. 我不认为你的两个第一个例子是等价的。 The first seems to be a closure, while the second uses a global constant. 第一个似乎是闭包,而第二个使用全局常量。 Anyway, for the first example, a direct equivalent in python would be 无论如何,对于第一个例子,python中的直接等价物将是

def f(x):
   def g(y):
      return x + y
   return g

and use it like 并使用它

add2 = f(2)
print(add2(3)) # == 5

Actually, your implementation using partial , does something similar under the hood 实际上,你的实现使用partial ,在引擎盖下做了类似的事情

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

相关问题 应用函数和返回多列的最pythonic方法是什么? - What is the most pythonic way to apply a function on and return multiple columns? 什么是在函数调用之间保存数据的pythonic方法? - What is the pythonic way of saving data between function calls? 重用生成器的最pythonic方式? - Most pythonic way to reuse a generator? 修改函数函数的最Pythonic方法是什么? - What is the most Pythonic way to modify the function of a function? 在此函数中传递kwargs的最pythonic方法是什么? - What is the most pythonic way to pass kwargs in this function? 什么是有条件地返回函数的最pythonic方式 - What is the most pythonic way to conditionally return a function 处理多个条件函数的大多数pythonic方式 - Most pythonic way of approaching a multiple conditionals function 在具有多种类型的空白字符的字符串中的每个单词上应用函数的最有效的方法是什么? - What's the most pythonic way to apply a function on every word in a string with multiple types of white space characters? 什么是避免在字符串中指定相同值的最pythonic方法 - What is the most pythonic way to avoid specifying the same value in a string 检查多个字典键是否匹配的最pythonic方法是什么 - What is most pythonic way to check if multiple dictionary keys match
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM