繁体   English   中英

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

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

通常我不会问这样的问题,但是python似乎有1.一个不同寻常的社区对习语的共识,并且通过使它们更具性能来鼓励它们(例如列表理解与地图,过滤器)。

这是我在编码时发现自己使用的模式,请考虑以下JavaScript:

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

或者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;
}

一些可能的方法转换为python:

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

或者可能:

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

bar = partial(foo, someInvariant)

要么:

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)

要么:

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

这是不幸的,现在取决于我走哪条路我可能不得不使用一个丢弃的名称作为初始函数定义,因为我只使用部分应用的版本,写了很多样板类(也有抛出 - 当它仅在一个函数中使用时,或者使用全局常量污染模块命名空间,或限制我的函数参数并确保有人可以通过使用错误数量的参数调用它来破坏它。

我也可以通过重新实例化每次通话来“解决”这个问题,并希望它会被优化掉,但由于我没有使用pypy,我对这个得分并不太有希望。

所以我的问题有两个方面:首先,有没有办法在没有权衡的情况下做到这一点? 第二,如果没有,上面哪个是最“pythonic”(惯用,高性能,合理等)?

贾里德,我完全明白你犹豫要问这个,因为它可以通过许多不同的意见来回答,并产生一场火焰战争。 但是,我同意你的看法:随着时间的推移,Python社区确实倾向于与许多实现问题保持一致。 这是Python的优势之一。

这是我的经验法则:如有疑问,请尽量使用Python标准库。 你对functools.partial直觉是正确的,原因如下:

  1. Python标准库是高度优化的C代码,它将超出您提出的任何Python类或函数闭包结构。
  2. Python标准库被其他Python程序员广泛使用,因此当您使用它时,其他Python程序员将更广泛地理解您的编码意图。 (“代码的读取频率高于编写代码。”)
  3. Python标准库由核心Python开发人员编写; 没有代码可能声称比标准库更“Pythonic”。

我希望有所帮助!

我建议一些通常是代码气味的东西 - 默认的可变参数。

琐碎的例子:

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

您的dict(或列表,或任何可变的)绑定到函数对象。 当省略cache关键字参数时,后续调用将引用同一对象。 此对象状态将在调用之间保持不变。

我不喜欢外部范围的var的想法,可能建议使用闭包,我认为这是更好的方式,因为你看它更像JavaScript,所以你可以使用函数作为对象:

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

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

还有一个你没有提到的替代方案,这是IMO最狡猾的方式,它不会创造一个扔掉的名字:)

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

虽然坚持使用std库是最好的。

我不认为你的两个第一个例子是等价的。 第一个似乎是闭包,而第二个使用全局常量。 无论如何,对于第一个例子,python中的直接等价物将是

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

并使用它

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

实际上,你的实现使用partial ,在引擎盖下做了类似的事情

暂无
暂无

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

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