为什么Python没有静态变量?
有一个问题问如何在python中模拟静态变量。
另外,在网上可以找到许多创建静态变量的解决方案。 (尽管我还没有看到我喜欢的一个。)
为什么Python不支持方法中的静态变量? 这被认为是非Python的,还是与Python的语法有关?
编辑:
我专门询问了为什么进行设计决策,但我没有提供任何代码示例,因为我想避免解释来模拟静态变量。
Georg Schölly asked 2020-02-22T23:28:07Z
9个解决方案
77 votes
忽略这一点的想法是,静态变量仅在以下两种情况下才有用:何时真正应该使用类以及何时真正应该使用生成器。
如果要将状态信息附加到函数,则需要一个类。 也许是一个简单的类,但是仍然是一个类:
def foo(bar):
static my_bar # doesn't work
if not my_bar:
my_bar = bar
do_stuff(my_bar)
foo(bar)
foo()
# -- becomes ->
class Foo(object):
def __init__(self, bar):
self.bar = bar
def __call__(self):
do_stuff(self.bar)
foo = Foo(bar)
foo()
foo()
如果您希望函数的行为在每次调用时都发生变化,则需要一个生成器:
def foo(bar):
static my_bar # doesn't work
if not my_bar:
my_bar = bar
my_bar = my_bar * 3 % 5
return my_bar
foo(bar)
foo()
# -- becomes ->
def foogen(bar):
my_bar = bar
while True:
my_bar = my_bar * 3 % 5
yield my_bar
foo = foogen(bar)
foo.next()
foo.next()
当然,静态变量对于那些不想处理小任务的大型结构的麻烦的快速脚本很有用。 但是在那儿,您实际上只需要global就可以了,这似乎有点麻烦,但是对于小的一次性脚本来说,这是可以的:
def foo():
global bar
do_stuff(bar)
foo()
foo()
Ben Blank answered 2020-02-22T23:28:34Z
19 votes
类的一种替代方法是函数属性:
def foo(arg):
if not hasattr(foo, 'cache'):
foo.cache = get_data_dict()
return foo.cache[arg]
虽然一门课可能更干净,但我认为这种技术可能有用并且更好,比全局性更好。
davidavr answered 2020-02-22T23:28:59Z
8 votes
在Python 3中,我将使用闭包:
def makefoo():
x = 0
def foo():
nonlocal x
x += 1
return x
return foo
foo = makefoo()
print(foo())
print(foo())
Josh Lee answered 2020-02-22T23:29:19Z
6 votes
我认为局部静态变量的大多数用途是模拟生成器,即具有执行某个过程迭代的某些函数,返回结果,但保留后续调用的状态。 Python使用yield命令非常优雅地处理了这一问题,因此似乎并不需要太多静态变量。
Il-Bhima answered 2020-02-22T23:29:39Z
5 votes
这是一种设计选择。
我假设Guido认为您不经常需要它们,而您从未真正需要它们:您始终可以只使用一个全局变量,并告诉每个人将它们的油腻腻的东西放在您的变量中;-)
Jonas Kölker answered 2020-02-22T23:30:04Z
4 votes
出于缓存或记忆的目的,装饰器可以用作一种优雅且通用的解决方案。
Mr Fooz answered 2020-02-22T23:30:24Z
0 votes
答案与为什么没人使用静态方法(即使它们存在)几乎相同。 您有一个模块级名称空间,其作用与类相同。
Jason Baker answered 2020-02-22T23:30:44Z
0 votes
一个不明智的选择:
您还可以使用函数默认值的定义时间评估的副作用:
def func(initial=0, my_static=[])
if not my_static:
my_static.append(initial)
my_static[0] += 1
return my_static[0]
print func(0), func(0), func(0)
它确实很丑陋,很容易被颠覆,但是有效。 imo,使用global比这更干净。
Richard Levasseur answered 2020-02-22T23:31:13Z
-1 votes
根据您的评论之一:“我想使用它们来缓存从磁盘加载的内容。如果可以将它们分配给函数,我认为它会使实例混乱的程度减少了”
然后,将缓存类用作其他类的类或实例属性。 这样,您可以使用完整的类功能集,而不会造成其他问题。 此外,您还将获得可重复使用的工具。
这表明,在SO上始终可以陈述一个人的问题,而不是要求一个特定的低级解决方案(例如缺少语言功能)。 这样一来,不必再有关于模拟“静态”(在我看来,这是古老语言中已弃用的功能)的无休止的辩论,而是可以早日给您一个很好的答案。
Ber answered 2020-02-22T23:31:43Z