函数中静态变量的Python等效项是什么?


630

此C / C ++代码的惯用Python等效项是什么?

void foo()
{
    static int counter = 0;
    counter++;
    printf("counter is %d\n", counter);
}

具体来说,如何在函数级别而非类级别实现静态成员?并将函数放入类中是否会发生任何变化?


22
等价我很害怕。即使使用函数属性对装饰器进行了修改,您也将能够访问外部的变量,这有点令人遗憾。而且,您将不得不在函数中对函数名称进行硬编码,这很烦人。我建议使用类或模块全局变量代替常规_前缀。
lpapp 2014年

8
对于非C程序员,[ stackoverflow.com/questions/5033627/…函数内的静态变量仅在该函数的作用域内可见,但其生存期是程序的整个生命周期,并且仅初始化一次)。基本上,持久计数器或存储变量位于函数调用之间。
smci

2
@lpapp:有点像,它是一个类成员。您是正确的,我们不能阻止其他代码查看或更改它。
smci

Answers:


681

有点相反,但这应该起作用:

def foo():
    foo.counter += 1
    print "Counter is %d" % foo.counter
foo.counter = 0

如果要将计数器初始化代码放在顶部而不是底部,则可以创建一个装饰器:

def static_vars(**kwargs):
    def decorate(func):
        for k in kwargs:
            setattr(func, k, kwargs[k])
        return func
    return decorate

然后使用如下代码:

@static_vars(counter=0)
def foo():
    foo.counter += 1
    print "Counter is %d" % foo.counter

foo.不幸的是,它仍然需要您使用前缀。

(信用:@ony


23
foo只有一个实例-这个函数。所有调用都访问相同的变量。
Claudiu

121
不好意思,我想把它if "counter" not in foo.__dict__: foo.counter = 0作为的第一行foo()。这将有助于避免函数外的代码。不确定在2008年是否有可能。PS在寻找创建静态函数变量的可能性时找到了这个答案,因此该线程仍然“活跃” :)
binaryLV

8
@binaryLV:我可能更喜欢第一种方法。第一种方法的问题在于,这种联系并没有立即显而易见,foofoo.counter = 没有密切的联系。但是,我最终还是喜欢装饰器方法,因为装饰器是不会被调用的,并且它的作用在语义上更加明显(@static_var("counter", 0)比起if "counter" not in foo.__dict__: foo.counter = 0,在我看来更容易,对我更有意义),尤其是在后者中,您必须使用函数名称(可能会更改两次)。
克劳迪乌

6
@lpapp:这取决于静态变量的含义。我一直以为这将满足多个函数调用的相同值。正如您所说的,我从来没有把它当作变量隐藏的对象。
Claudiu 2014年

3
def foo(): if not hasattr(foo,"counter"): foo.counter=0 foo.counter += 1
Erik Aronesty'1

221

您可以向函数添加属性,并将其用作静态变量。

def myfunc():
  myfunc.counter += 1
  print myfunc.counter

# attribute must be initialized
myfunc.counter = 0

另外,如果您不想在函数外部设置变量,则hasattr()可以避免出现AttributeError异常:

def myfunc():
  if not hasattr(myfunc, "counter"):
     myfunc.counter = 0  # it doesn't exist yet, so initialize it
  myfunc.counter += 1

无论如何,静态变量很少见,您应该为该变量找到一个更好的位置,很可能在类中。


6
为什么不尝试代替if语句呢?
ravwojdyla 2013年

12
try: myfunc.counter += 1; except AttributeError: myfunc.counter = 1应该使用异常来做同样的事情。
sleblanc 2013年

异常应用于异常情况,即程序员期望不会发生的异常,例如已成功打开的输入文件突然不可用。这是预期的情况,if语句更有意义。
Hack Saw 2014年

11
@Hack_Saw:嗯,这是Pythonic的(要求宽恕而不是允许)。实际上,这是Python优化技术中推荐的方法,因为它可以节省if的成本(尽管我不建议过早的优化)。关于例外情况的规则:1.从某种意义上说,失败是例外情况。它只会发生一次。2.我认为规则是关于使用(即引发)异常的。对于您希望工作但有备份计划的事情,这是一个例外,这在大多数语言中是很常见的。
leewz 2014年

@leewangzhong:封闭一个不会引发异常的块会try增加成本吗?只是好奇。
trss 2014年

201

还可以考虑:

def foo():
    try:
        foo.counter += 1
    except AttributeError:
        foo.counter = 1

推理:

  • 大量pythonic(“请求宽恕而不是许可”)
  • 使用异常(仅抛出一次)而不是if分支(请考虑StopIteration异常)

11
我使用Python的时间并不长,但是这满足了该语言的一种隐含特点:如果(相当)不容易,则您做错了
ZX9

无法立即使用类方法,“ self.foo.counter = 1”再次引发AttributeError。
villasv

16
这是正确的解决方案,应该是可接受的答案,因为初始化代码将在调用函数时运行,而不是在模块执行时或从模块中导入某些东西时运行,如果您使用来自当前接受的答案。请参阅Python装饰器函数执行。如果您有一个巨大的库模块,那么每个装饰器都会运行,包括那些您不导入的功能。
尼尔斯·林德曼

3
一个更简单的方法: def fn(): if not hasattr(fn, 'c'): fn.c = 0 fn.c += 1 return fn.c
TheCuriousOne

5
@MANU hasattr()这样做并不简单,效率也较低。
moooeeeep

48

其他答案已经说明了您应该执行此操作的方式。这是您不应该使用的方法:

>>> def foo(counter=[0]):
...   counter[0] += 1
...   print("Counter is %i." % counter[0]);
... 
>>> foo()
Counter is 1.
>>> foo()
Counter is 2.
>>> 

仅在第一次评估该函数时才初始化缺省值,而不是在每次执行该函数时才初始化缺省值,因此可以使用列表或任何其他可变对象存储静态值。


我尝试过,但是由于某种原因,函数参数将自身初始化为140,而不是0。为什么会这样呢?
andrewdotnich

1
@bouvard对于需要静态变量的递归函数,这是唯一真正读懂的函数。
lifebalance 2015年

1
我尝试了几种方法,但愿这一方法能被pythonic接受。像def foo(arg1, arg2, _localstorage=DataClass(counter=0))我这样的有意义的名字,我觉得它很好读。另一个好处是易于重命名功能。
VPfB

2
为什么说您不应该那样做?对我来说看起来很合理!
康斯坦丁

1
@VPfB:对于常规存储,您可以使用types.SimpleNamespacedef foo(arg1, arg2, _staticstorage=types.SimpleNamespace(counter=0)):而无需定义特殊的类。
ShadowRanger

43

很多人已经建议测试“ hasattr”,但是答案很简单:

def func():
    func.counter = getattr(func, 'counter', 0) + 1

没有try / except,没有测试hasattr,只有默认的getattr。


2
当您在其中放置函数时,请注意getattr的第三个参数:def func():def foo():return 1112 func.counter = getattr(func,'counter',foo())+ 1 func,foo将永远被调用!
Codefor

1
每次调用func时,只需调用getattr。如果性能不是问题,那很好,如果它是try / except,那将会很成功。
马克·劳伦斯

2
@MarkLawrence:实际上,至少在我的Windows x64 3.8.0安装上,此答案与ravwojdyla的等效方法try/ except基于方法之间的性能差异是毫无意义的。一个简单的ipython %%timeit微基准给成本try/ except每调用255纳秒,与263纳秒为getattr基础的解决方案。是的,try/ except速度更快,但这并不是完全“放手”。这是一个微小的微优化。编写看起来更清晰的代码,不必担心这样的琐碎性能差异。
ShadowRanger

@ShadowRanger感谢基准测试。我一直想知道MarkLawrence的声明已经2年了,很高兴您进行了这项研究。我绝对同意您的最后一句话-“编写任何看起来更清晰的代码”-这正是我编写此答案的原因。
乔纳森

28

这是一个完全封装的版本,不需要外部初始化调用:

def fn():
    fn.counter=vars(fn).setdefault('counter',-1)
    fn.counter+=1
    print (fn.counter)

在Python中,函数是对象,我们可以通过special属性将成员变量简单地添加或猴子补丁__dict__。内置vars()函数返回special属性__dict__

编辑:请注意,与替代try:except AttributeError答案不同,使用此方法,变量将始终为初始化后的代码逻辑做好准备。我认为以下try:except AttributeError替代方案将减少DRY和/或流程笨拙:

def Fibonacci(n):
   if n<2: return n
   Fibonacci.memo=vars(Fibonacci).setdefault('memo',{}) # use static variable to hold a results cache
   return Fibonacci.memo.setdefault(n,Fibonacci(n-1)+Fibonacci(n-2)) # lookup result in cache, if not available then calculate and store it

EDIT2:仅当从多个位置调用该函数时,才建议使用上述方法。如果只在一个地方调用该函数,则最好使用nonlocal

def TheOnlyPlaceStaticFunctionIsCalled():
    memo={}
    def Fibonacci(n):
       nonlocal memo  # required in Python3. Python2 can see memo
       if n<2: return n
       return memo.setdefault(n,Fibonacci(n-1)+Fibonacci(n-2))
    ...
    print (Fibonacci(200))
    ...

2
唯一的问题是,它实际上根本不是整洁的,每当您要使用此模式时,都必须剪切并粘贴代码...因此,我使用装饰器
Claudiu 2013年

2
可能应该使用类似的东西try: mystaticfun.counter+=10 except AttributeError: mystaticfun.counter=0
endolith

2
请使用X not in Y而不是not X in Y(或建议使用,如果您只是在使用它,以便与进行更相似的比较hasattr
Nick T

怎么样: def fn(): if not hasattr(fn, 'c'): fn.c = 0 fn.c += 1 return fn.c
TheCuriousOne

它不是理想的,因为if子句添加了不必要的嵌套,在这种情况下,我更喜欢setdefault
Riaz Rizvi

27

Python没有静态变量,但是您可以通过定义可调用的类对象然后将其用作函数来伪造它。另请参阅此答案

class Foo(object):
  # Class variable, shared by all instances of this class
  counter = 0

  def __call__(self):
    Foo.counter += 1
    print Foo.counter

# Create an object instance of class "Foo," called "foo"
foo = Foo()

# Make calls to the "__call__" method, via the object's name itself
foo() #prints 1
foo() #prints 2
foo() #prints 3

请注意,这__call__使得类(对象)的实例可以通过其自己的名称来调用。这就是为什么foo()上面的调用会调用类的__call__方法的原因。从文档中

可以通过在任意类的类中定义一个__call__()方法来使其实例化。


15
函数已经是对象,因此仅添加了不必要的层。
DasIch 2011年

看到这样的答案很长的意见,这实际上是一个好主意。 stackoverflow.com/questions/460586。我同意,使任何此类都成为一个单例,也许像这个stackoverflow.com/questions/6760685一样,也是一个好主意。我不知道@ S.Lott的意思是“ ...将计数器移到类定义中...”,因为它对我来说似乎已经处于类变量位置。
Reb.Cabin

1
根据我的研究,此类技术似乎是本页介绍的方法中最“ Pythonic”的方法,并且使用最少的技巧。因此,我计划将其作为我自己的新Python开发人员来替代函数中类似C静态变量的功能。
加布里埃尔·斯台普斯

1
如果我想要foo1 = Foo()和foo2 = Foo()会发生什么?
马克·劳伦斯

@MarkLawrence然后,您有两个不同的可调用类实例,每个实例都有自己的计数器。如果您不使用foo作为单例提供的实例,那该期待什么呢?
亚伦·麦克米林

14

使用生成器函数生成迭代器。

def foo_gen():
    n = 0
    while True:
        n+=1
        yield n

然后像

foo = foo_gen().next
for i in range(0,10):
    print foo()

如果需要上限:

def foo_gen(limit=100000):
    n = 0
    while n < limit:
       n+=1
       yield n

如果迭代器终止(如上面的示例),您也可以直接在其上循环,例如

for i in foo_gen(20):
    print i

当然,在这些简单的情况下,最好使用xrange :)

这是关于yield声明的文档。


11

其他解决方案通常使用复杂的逻辑来将计数器属性添加到函数,以处理初始化。这不适用于新代码。

在Python 3中,正确的方法是使用以下nonlocal语句:

counter = 0
def foo():
    nonlocal counter
    counter += 1
    print(f'counter is {counter}')

有关声明的说明,请参见PEP 3104nonlocal

如果计数器是模块专用的,则应_counter改为命名。


即使在Python 3之前,您也总是可以使用global counter语句代替nonlocal counternonlocal只是让您在嵌套函数中写入闭包状态)来执行此操作。人们向该函数附加属性的原因是避免为该函数特定的状态污染全局命名空间,因此,当两个函数需要独立的counters 时,您甚至不必做更棘手的事情。此解决方案无法扩展;功能上的属性。kdb的答案是如何提供nonlocal帮助,但这确实增加了复杂性。
ShadowRanger

嗯,我认为除非您经常这样做,否则工厂功能或装饰器的复杂性就显得过高了,在这种情况下,设计已经有些难闻了。要一次性完成,只需添加非本地计数器即可。我在有关命名约定的答案中添加了一些内容。另外,我建议的原因nonlocalglobal是完全按照你所指出的-它工作在严格的更多情况。
cbarrick

8

将函数的属性用作静态变量有一些潜在的缺点:

  • 每次您要访问变量时,都必须写出函数的全名。
  • 外部代码可以轻松访问变量并弄乱值。

第二个问题的惯用python可能是用一个前导下划线将变量命名,以表示该变量不是可被访问的,而在事发后仍可访问。

另一种选择是使用词法闭包的模式,这nonlocal在python 3 中受关键字支持。

def make_counter():
    i = 0
    def counter():
        nonlocal i
        i = i + 1
        return i
    return counter
counter = make_counter()

可悲的是,我不知道将这种解决方案封装到装饰器中的方法。


7
def staticvariables(**variables):
    def decorate(function):
        for variable in variables:
            setattr(function, variable, variables[variable])
        return function
    return decorate

@staticvariables(counter=0, bar=1)
def foo():
    print(foo.counter)
    print(foo.bar)

就像上面的vincent的代码一样,它将用作函数装饰器,并且必须使用函数名称作为前缀来访问静态变量。该代码的优点(尽管可以承认,任何人都可以聪明地解决它)是您可以拥有多个静态变量,并可以以更常规的方式对其进行初始化。


7

更具可读性,但更冗长(Python的Zen:显式优于隐式):

>>> def func(_static={'counter': 0}):
...     _static['counter'] += 1
...     print _static['counter']
...
>>> func()
1
>>> func()
2
>>>

请参阅此处以了解其工作原理。


您能详细说明为什么此代码有效吗?第二个foo()应该将字典重新初始化为函数定义中指定的值(因此计数器键的值为0)。为什么不呢?
raffaem

3
@raffamaiden:默认参数仅在定义函数时才评估一次,而不是在每次调用函数时才评估。
Daniel K.19年

6
_counter = 0
def foo():
   全局_counter
   _counter + = 1
   打印“计数器是”,_counter

Python通常使用下划线指示私有变量。C语言中在函数内部声明静态变量的唯一原因是将其隐藏在函数外部,这并不是真正的Python。


4

在尝试了几种方法之后,我最终使用了@warvariuc的答案的改进版本:

import types

def func(_static=types.SimpleNamespace(counter=0)):
    _static.counter += 1
    print(_static.counter)

3

惯用的方法是使用一个,它可以有属性。如果需要不分离实例,请使用单例。

您可以通过多种方法将“静态”变量伪造或修改为Python(到目前为止,尚未提及的一种方法是使用可变的默认参数),但这不是Pythonic惯用的方法。只需使用一个类。

如果您的使用模式合适,则可能是生成器。


对于独立的递归函数,default参数是最优雅的一种。
平衡

3

这个问题的提示下,我可以提出另一种选择,它可能会更好用,并且对于方法和函数来说都一样:

@static_var2('seed',0)
def funccounter(statics, add=1):
    statics.seed += add
    return statics.seed

print funccounter()       #1
print funccounter(add=2)  #3
print funccounter()       #4

class ACircle(object):
    @static_var2('seed',0)
    def counter(statics, self, add=1):
        statics.seed += add
        return statics.seed

c = ACircle()
print c.counter()      #1
print c.counter(add=2) #3
print c.counter()      #4
d = ACircle()
print d.counter()      #5
print d.counter(add=2) #7
print d.counter()      #8    

如果您喜欢这种用法,请执行以下操作:

class StaticMan(object):
    def __init__(self):
        self.__dict__['_d'] = {}

    def __getattr__(self, name):
        return self.__dict__['_d'][name]
    def __getitem__(self, name):
        return self.__dict__['_d'][name]
    def __setattr__(self, name, val):
        self.__dict__['_d'][name] = val
    def __setitem__(self, name, val):
        self.__dict__['_d'][name] = val

def static_var2(name, val):
    def decorator(original):
        if not hasattr(original, ':staticman'):    
            def wrapped(*args, **kwargs):
                return original(getattr(wrapped, ':staticman'), *args, **kwargs)
            setattr(wrapped, ':staticman', StaticMan())
            f = wrapped
        else:
            f = original #already wrapped

        getattr(f, ':staticman')[name] = val
        return f
    return decorator

3

另一个(不建议!)在可调用对象(如https://stackoverflow.com/a/279598/916373)上的扭曲,如果您不介意使用时髦的调用签名,则可以这样做

class foo(object):
    counter = 0;
    @staticmethod
    def __call__():
        foo.counter += 1
        print "counter is %i" % foo.counter

>>> foo()()
counter is 1
>>> foo()()
counter is 2

3

除了创建具有静态局部变量的函数外,您始终可以创建所谓的“函数对象”并为其提供标准(非静态)成员变量。

由于您提供了用C ++编写的示例,因此我将首先解释C ++中的“函数对象”。“功能对象”就是带有重载的任何类operator()。该类的实例的行为类似于函数。例如,int x = square(5);即使square是一个对象(具有重载operator()),但从技术上讲不是“函数” ,您也可以编写。您可以给功能对象提供可以给类对象提供的任何功能。

# C++ function object
class Foo_class {
    private:
        int counter;     
    public:
        Foo_class() {
             counter = 0;
        }
        void operator() () {  
            counter++;
            printf("counter is %d\n", counter);
        }     
   };
   Foo_class foo;

在Python中,我们也可以重载,operator()只是方法改为命名为__call__

这是一个类定义:

class Foo_class:
    def __init__(self): # __init__ is similair to a C++ class constructor
        self.counter = 0
        # self.counter is like a static member
        # variable of a function named "foo"
    def __call__(self): # overload operator()
        self.counter += 1
        print("counter is %d" % self.counter);
foo = Foo_class() # call the constructor

这是使用的类的示例:

from foo import foo

for i in range(0, 5):
    foo() # function call

打印到控制台的输出是:

counter is 1
counter is 2
counter is 3
counter is 4
counter is 5

如果要让函数接受输入参数,也可以将其添加到其中__call__

# FILE: foo.py - - - - - - - - - - - - - - - - - - - - - - - - -

class Foo_class:
    def __init__(self):
        self.counter = 0
    def __call__(self, x, y, z): # overload operator()
        self.counter += 1
        print("counter is %d" % self.counter);
        print("x, y, z, are %d, %d, %d" % (x, y, z));
foo = Foo_class() # call the constructor

# FILE: main.py - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

from foo import foo

for i in range(0, 5):
    foo(7, 8, 9) # function call

# Console Output - - - - - - - - - - - - - - - - - - - - - - - - - - 

counter is 1
x, y, z, are 7, 8, 9
counter is 2
x, y, z, are 7, 8, 9
counter is 3
x, y, z, are 7, 8, 9
counter is 4
x, y, z, are 7, 8, 9
counter is 5
x, y, z, are 7, 8, 9

3

溶液n + = 1

def foo():
  foo.__dict__.setdefault('count', 0)
  foo.count += 1
  return foo.count

3

全局声明提供了此功能。在下面的示例(使用“ f”的python 3.5或更高版本)中,计数器变量在函数外部定义。在功能中将其定义为全局表示表示该功能之外的“全局”版本应可用于该功能。因此,每次函数运行时,它都会修改函数外部的值,并将其保留在函数之外。

counter = 0

def foo():
    global counter
    counter += 1
    print("counter is {}".format(counter))

foo() #output: "counter is 1"
foo() #output: "counter is 2"
foo() #output: "counter is 3"

如果正确使用,则其工作方式相同。与c代码的不同之处在于,在OP的c示例中,计数器变量只能由该函数触摸。python中的全局变量可以在脚本中的任何位置使用或更改
MortenSickel,

2

Python方法内的静态变量

class Count:
    def foo(self):
        try: 
            self.foo.__func__.counter += 1
        except AttributeError: 
            self.foo.__func__.counter = 1

        print self.foo.__func__.counter

m = Count()
m.foo()       # 1
m.foo()       # 2
m.foo()       # 3

1

我个人更喜欢以下装饰器。给每个人自己。

def staticize(name, factory):
    """Makes a pseudo-static variable in calling function.

    If name `name` exists in calling function, return it. 
    Otherwise, saves return value of `factory()` in 
    name `name` of calling function and return it.

    :param name: name to use to store static object 
    in calling function
    :type name: String
    :param factory: used to initialize name `name` 
    in calling function
    :type factory: function
    :rtype: `type(factory())`

    >>> def steveholt(z):
    ...     a = staticize('a', list)
    ...     a.append(z)
    >>> steveholt.a
    Traceback (most recent call last):
    ...
    AttributeError: 'function' object has no attribute 'a'
    >>> steveholt(1)
    >>> steveholt.a
    [1]
    >>> steveholt('a')
    >>> steveholt.a
    [1, 'a']
    >>> steveholt.a = []
    >>> steveholt.a
    []
    >>> steveholt('zzz')
    >>> steveholt.a
    ['zzz']

    """
    from inspect import stack
    # get scope enclosing calling function
    calling_fn_scope = stack()[2][0]
    # get calling function
    calling_fn_name = stack()[1][3]
    calling_fn = calling_fn_scope.f_locals[calling_fn_name]
    if not hasattr(calling_fn, name):
        setattr(calling_fn, name, factory())
    return getattr(calling_fn, name)

3
请不要冒犯,但此解决方案让我有点“大公司风格” :-) willa.me/2013/11/the-six-most-common-species-of-code.html
JJC

是的,使用非便携式(堆栈操作通常是CPython实现的细节,不是您可以在PyPy,Jython,IronPython,您拥有的东西中依赖的东西),脆弱的堆栈操作,每次使用都会调用六个函数是方式比简单更好装饰... </ S>
ShadowRanger

1

此答案基于@claudiu的答案。

我发现,每当我打算访问静态变量时,总是必须在函数名称前加上前缀,我的代码变得不清楚。

即,在我的函数代码中,我更喜欢写:

print(statics.foo)

代替

print(my_function_name.foo)

因此,我的解决方案是:

  1. 添加一个 statics向函数属性
  2. 在功能范围中,将局部变量添加statics为别名my_function.statics
from bunch import *

def static_vars(**kwargs):
    def decorate(func):
        statics = Bunch(**kwargs)
        setattr(func, "statics", statics)
        return func
    return decorate

@static_vars(name = "Martin")
def my_function():
    statics = my_function.statics
    print("Hello, {0}".format(statics.name))

备注

我的方法使用一个名为的类Bunch,它是一个支持属性样式访问的字典,即JavaScript(请参见原始文章)。 2000年前后)

可以通过安装 pip install bunch

也可以这样手写:

class Bunch(dict):
    def __init__(self, **kw):
        dict.__init__(self,kw)
        self.__dict__ = self

注意:(types.SimpleNamespace自3.3起可用)开箱即用地支持此行为(并且在CPython上的C中实现,因此它的速度尽可能快)。
ShadowRanger

0

基于丹尼尔的答案(补充):

class Foo(object): 
    counter = 0  

def __call__(self, inc_value=0):
    Foo.counter += inc_value
    return Foo.counter

foo = Foo()

def use_foo(x,y):
    if(x==5):
        foo(2)
    elif(y==7):
        foo(3)
    if(foo() == 10):
        print("yello")


use_foo(5,1)
use_foo(5,1)
use_foo(1,7)
use_foo(1,7)
use_foo(1,1)

我想添加此部分的原因是,作为一个实际示例,静态变量不仅用于增加某个值,而且还检查静态var是否等于某个值。

静态变量仍受保护,仅在函数use_foo()的范围内使用

在此示例中,对foo()的调用功能完全相同(相对于相应的c ++等效项):

stat_c +=9; // in c++
foo(9)  #python equiv

if(stat_c==10){ //do something}  // c++

if(foo() == 10):      # python equiv
  #add code here      # python equiv       

Output :
yello
yello

如果将Foo类限制性地定义为单例类,那将是理想的。这将使它更具Pythonic性。


-1

当然,这是一个老问题,但我想我可能会提供一些更新。

似乎性能参数已过时。相同的测试套件似乎为siInt_try和isInt_re2提供了相似的结果。当然结果会有所不同,但这是在我的计算机上使用Xeon W3550在内核4.3.01上使用python 3.4.4的会话。我已经运行了几次,结果似乎是相似的。我将全局正则表达式移到了函数静态中,但是性能差异可以忽略不计。

isInt_try: 0.3690
isInt_str: 0.3981
isInt_re: 0.5870
isInt_re2: 0.3632

随着性能问题的解决,try / catch似乎会生成最适合未来和极端情况的代码,因此也许将其包装在函数中


1
您什至在这里比较什么?这似乎是对其他答案的评论,但不清楚哪个答案,也无法回答问题本身。
ShadowRanger
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.