There is a questions asking how to simulate static variables in python.
有一个问题询问如何在python中模拟静态变量。
Also, on the web one can find many different solutions to create static variables. (Though I haven't seen one that I like yet.)
此外,在Web上可以找到许多不同的解决方案来创建静态变量。 (虽然我还没有看到我喜欢的那个。)
Why doesn't Python support static variables in methods? Is this considered unpythonic or has it something to do with Python's syntax?
为什么Python不支持方法中的静态变量?这被认为是unpythonic还是与Python的语法有关?
Edit:
编辑:
I asked specifically about the why of the design decision and I haven't provided any code example because I wanted to avoid explanation to simulate static variables.
我特意询问了设计决策的原因,但我没有提供任何代码示例,因为我想避免解释来模拟静态变量。
9 个解决方案
#1
75
The idea behind this omission is that static variables are only useful in two situations: when you really should be using a class and when you really should be using a generator.
这个省略背后的想法是静态变量只在两种情况下有用:当你真的应该使用一个类时,你何时应该使用一个生成器。
If you want to attach stateful information to a function, what you need is a class. A trivially simple class, perhaps, but a class nonetheless:
如果要将有状态信息附加到函数,则需要的是类。也许是一个简单的简单课程,但仍然是一个课程:
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()
If you want your function's behavior to change each time it's called, what you need is a generator:
如果您希望每次调用函数的行为都会改变,那么您需要的是生成器:
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()
Of course, static variables are useful for quick-and-dirty scripts where you don't want to deal with the hassle of big structures for little tasks. But there, you don't really need anything more than global
— it may seem a but kludgy, but that's okay for small, one-off scripts:
当然,静态变量对于快速而肮脏的脚本非常有用,在这些脚本中,您不希望处理小型任务的大型结构的麻烦。但是在那里,你真的不需要任何比全局更多的东西 - 它可能看起来像一个但很笨拙,但这对于小型的一次性脚本来说是可以的:
def foo():
global bar
do_stuff(bar)
foo()
foo()
#2
19
One alternative to a class is a function attribute:
类的一种替代方法是函数属性:
def foo(arg):
if not hasattr(foo, 'cache'):
foo.cache = get_data_dict()
return foo.cache[arg]
While a class is probably cleaner, this technique can be useful and is nicer, in my opinion, then a global.
虽然一个类可能更干净,但这种技术可能很有用,而且在我看来更好,然后是全球性的。
#3
8
In Python 3, I would use a closure:
在Python 3中,我会使用一个闭包:
def makefoo():
x = 0
def foo():
nonlocal x
x += 1
return x
return foo
foo = makefoo()
print(foo())
print(foo())
#4
6
I think most uses of local static variables is to simulate generators, that is, having some function which performs some iteration of a process, returns the result, but mantains the state for the subsequent invocation. Python handles this very elegantly using the yield
command, so it seems there is not so much need for static variables.
我认为局部静态变量的大多数用法是模拟生成器,也就是说,有一些函数执行某个进程的迭代,返回结果,但保留后续调用的状态。 Python使用yield命令非常优雅地处理它,因此似乎不需要静态变量。
#5
5
It's a design choice.
这是一个设计选择。
I'm assuming Guido thinks you don't need them very often, and you never really need them: you can always just use a global variable and tell everyone to keep their greasy paws offa' your variable ;-)
我假设Guido认为你不经常需要它们,而且你从来没有真正需要它们:你总是可以使用一个全局变量并告诉每个人让他们的油腻爪子离开你的变量;-)
#6
4
For caching or memoization purposes, decorators can be used as an elegant and general solution.
出于缓存或记忆的目的,装饰器可以用作优雅且通用的解决方案。
#7
0
The answer's pretty much the same as why nobody uses static methods (even though they exist). You have a module-level namespace that serves about the same purpose as a class would anyway.
答案与为什么没有人使用静态方法(即使它们存在)几乎相同。你有一个模块级命名空间,它的用途与类无关。
#8
0
An ill-advised alternative:
一个不明智的选择:
You can also use the side-effects of the definition time evaluation of function defaults:
您还可以使用函数默认值的定义时间评估的副作用:
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)
Its really ugly and easily subverted, but works. Using global
would be cleaner than this, imo.
它真的很丑陋,容易被颠覆,但有效。使用全球将比这更清洁,imo。
#9
-1
From one of your comments: "I'd like to use them to cache things loaded from disk. I think it clutters the instance less, if I could assign them to the function"
从你的一条评论中说:“我想用它们来缓存从磁盘加载的东西。我认为如果我可以将它们分配给函数,它会使实例更加混乱”
Use a caching class then, as a class or instance attribute to your other class. That way, you can use the full feature set of classes without cluttering other things. Also, you get a reusable tool.
然后使用缓存类作为其他类的类或实例属性。这样,您可以使用完整的类功能集而不会混淆其他内容。此外,您还可以获得可重用的工具。
This shows that on SO it always pays off to state one's problem instead of asking for a specific, low level solution (e.g. for a missing language feature). That way, instead of endless debates about simulating "static" (a deprecated feature from an ancient language, in my view) someone could have given a good answer to you problem sooner.
这表明在SO上总是能够说明一个问题而不是要求特定的低级解决方案(例如,缺少语言特征)。这样,有人可以更快地给你一个很好的答案,而不是关于模拟“静态”(古代语言的一个不赞成的特征,在我看来)的无休止的争论。
#1
75
The idea behind this omission is that static variables are only useful in two situations: when you really should be using a class and when you really should be using a generator.
这个省略背后的想法是静态变量只在两种情况下有用:当你真的应该使用一个类时,你何时应该使用一个生成器。
If you want to attach stateful information to a function, what you need is a class. A trivially simple class, perhaps, but a class nonetheless:
如果要将有状态信息附加到函数,则需要的是类。也许是一个简单的简单课程,但仍然是一个课程:
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()
If you want your function's behavior to change each time it's called, what you need is a generator:
如果您希望每次调用函数的行为都会改变,那么您需要的是生成器:
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()
Of course, static variables are useful for quick-and-dirty scripts where you don't want to deal with the hassle of big structures for little tasks. But there, you don't really need anything more than global
— it may seem a but kludgy, but that's okay for small, one-off scripts:
当然,静态变量对于快速而肮脏的脚本非常有用,在这些脚本中,您不希望处理小型任务的大型结构的麻烦。但是在那里,你真的不需要任何比全局更多的东西 - 它可能看起来像一个但很笨拙,但这对于小型的一次性脚本来说是可以的:
def foo():
global bar
do_stuff(bar)
foo()
foo()
#2
19
One alternative to a class is a function attribute:
类的一种替代方法是函数属性:
def foo(arg):
if not hasattr(foo, 'cache'):
foo.cache = get_data_dict()
return foo.cache[arg]
While a class is probably cleaner, this technique can be useful and is nicer, in my opinion, then a global.
虽然一个类可能更干净,但这种技术可能很有用,而且在我看来更好,然后是全球性的。
#3
8
In Python 3, I would use a closure:
在Python 3中,我会使用一个闭包:
def makefoo():
x = 0
def foo():
nonlocal x
x += 1
return x
return foo
foo = makefoo()
print(foo())
print(foo())
#4
6
I think most uses of local static variables is to simulate generators, that is, having some function which performs some iteration of a process, returns the result, but mantains the state for the subsequent invocation. Python handles this very elegantly using the yield
command, so it seems there is not so much need for static variables.
我认为局部静态变量的大多数用法是模拟生成器,也就是说,有一些函数执行某个进程的迭代,返回结果,但保留后续调用的状态。 Python使用yield命令非常优雅地处理它,因此似乎不需要静态变量。
#5
5
It's a design choice.
这是一个设计选择。
I'm assuming Guido thinks you don't need them very often, and you never really need them: you can always just use a global variable and tell everyone to keep their greasy paws offa' your variable ;-)
我假设Guido认为你不经常需要它们,而且你从来没有真正需要它们:你总是可以使用一个全局变量并告诉每个人让他们的油腻爪子离开你的变量;-)
#6
4
For caching or memoization purposes, decorators can be used as an elegant and general solution.
出于缓存或记忆的目的,装饰器可以用作优雅且通用的解决方案。
#7
0
The answer's pretty much the same as why nobody uses static methods (even though they exist). You have a module-level namespace that serves about the same purpose as a class would anyway.
答案与为什么没有人使用静态方法(即使它们存在)几乎相同。你有一个模块级命名空间,它的用途与类无关。
#8
0
An ill-advised alternative:
一个不明智的选择:
You can also use the side-effects of the definition time evaluation of function defaults:
您还可以使用函数默认值的定义时间评估的副作用:
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)
Its really ugly and easily subverted, but works. Using global
would be cleaner than this, imo.
它真的很丑陋,容易被颠覆,但有效。使用全球将比这更清洁,imo。
#9
-1
From one of your comments: "I'd like to use them to cache things loaded from disk. I think it clutters the instance less, if I could assign them to the function"
从你的一条评论中说:“我想用它们来缓存从磁盘加载的东西。我认为如果我可以将它们分配给函数,它会使实例更加混乱”
Use a caching class then, as a class or instance attribute to your other class. That way, you can use the full feature set of classes without cluttering other things. Also, you get a reusable tool.
然后使用缓存类作为其他类的类或实例属性。这样,您可以使用完整的类功能集而不会混淆其他内容。此外,您还可以获得可重用的工具。
This shows that on SO it always pays off to state one's problem instead of asking for a specific, low level solution (e.g. for a missing language feature). That way, instead of endless debates about simulating "static" (a deprecated feature from an ancient language, in my view) someone could have given a good answer to you problem sooner.
这表明在SO上总是能够说明一个问题而不是要求特定的低级解决方案(例如,缺少语言特征)。这样,有人可以更快地给你一个很好的答案,而不是关于模拟“静态”(古代语言的一个不赞成的特征,在我看来)的无休止的争论。