静态变量模拟:类与生成器
我对在Python中使用静态变量感到好奇,结果找到了这个链接:为什么Python没有静态变量?
在我觉得很有用的一个被接受的回答中提到:“如果你希望函数每次被调用时行为都不同,你需要的是一个生成器。”
不过我有点困惑,因为那里的例子其实也可以用类来实现:
class Foo(object):
def __init__(self, bar):
self.bar = bar
def __call__(self):
self.bar = self.bar * 3 % 5
return self.bar
foo = Foo(bar)
print foo()
print foo()
这对我来说更有意义(但可能只是因为我之前没有好好使用过生成器)。
所以我的问题是,当函数每次需要改变行为时,使用生成器相比于类还有其他好处吗?
4 个回答
2
一个合适的生成器类看起来是这样的:
class Foo(object):
def __init__(self, bar):
self.bar = bar
def __iter__(self):
return self
def next(self):
self.bar = self.bar * 3 % 5
return self.bar
foo = Foo(3)
print next(foo)
print next(foo)
相应的生成器函数只需要一半的代码:
def Foo(bar):
while True:
bar = bar * 3 % 5
yield bar
foo = Foo(3)
print next(foo)
print next(foo)
生成器函数其实就是一种简化写法,用来处理最常见的循环方式。当你需要更复杂的功能时,使用类会更合适。
2
用生成器能做的事情,类也能做到。
使用生成器的原因很简单,就是它们写起来更简洁,而且在很多情况下比类更容易理解。当然,这也要看你具体在做什么。在你举的例子中,你只是想重复执行相同的操作并输出数字,所以用生成器非常合适。如果情况更复杂一些,那就应该用类。
3
生成器(这里说的简单生成器,不涉及协程)有一个非常明确的目的:编写迭代器。为了实现这个目的,你可以隐式地捕获局部变量,并使用一个关键字来暂停执行(而不是“终止”——你可以继续执行),然后给调用者返回迭代器的下一个值。使用生成器的好处有:
- 逻辑更自然,因为你不需要把代码拆分成多个方法调用——所有的状态都被保留,包括程序计数器——你可以在生成值的过程中使用控制流。你可以把
yield x
替换成results.append(x)
,然后在最后用return results
,这样就能得到一个和list(the_original_generator(...))
等价的函数。 - 你不需要通过放入
self
来显式地让值保持长久——这样打字更少,阅读起来也更轻松。 - 你不需要写一个类声明和两个方法声明(这些都是一些额外的代码,在Python中算是比较麻烦的)。
你 可以 利用“捕获局部变量”的特性来实现一个可迭代对象,虽然这样你可以有多个这样的对象,并且你使用的是迭代器(比如用 next_val = next(vals)
而不是 next_val = vals()
)。是否合适就要看具体情况了。