是否有内置/推荐的方法来替换装饰器:
def generator(f):
return f()
在以下示例中?
from random import randint
@generator
def mygenerator():
while True:
yield randint(0, 9)
for i in mygenerator:
print i
......因为我不想写:
for i in mygenerator():
print i
这是一个简化的例子。在实际用例中,没有必要/理由有两个mygenerator
实例,因此我想立即创建实例。优选地,不能创建其他实例。
答案 0 :(得分:2)
内置的方法是这样的:
def mygenerator():
while True:
yield randint(0, 9)
mygenerator = mygenerator()
这至少具有明确的优点,因此您不必查看@generator
所做的事情。
答案 1 :(得分:2)
可以使用()
语法创建生成器 - 即
mygenerator = (randint(0, 9) for i in range(0, 100))
但是我的问题是,你的问题是发电机是无限的 - 你可以试试这个:
import itertools
from random import randint
mygenerator = (randint(0, 9) for i in itertools.count())
有关其他详细信息,请参阅this answer
答案 2 :(得分:1)
你正在做的事情就像它可能是惯用的一样。有些语言有一个名为do
的二进制前缀运算符,用于调用其参数:
generator = do <generator expression>
Python语法不允许您将多行函数编写为表达式。您必须使用def
语句。这就是为什么你不能使用Python中的常规调用将多行函数或生成器传递给装饰器的原因:
generator = decorator(def generator(): yield) # syntax error
您必须预先定义功能或生成器:
def generator(): yield
generator = decorator(generator)
主要是语法限制迫使Python采用@
语法来装饰用def
语句定义的函数。以下代码等同于最后一个示例(除了分配名称时的细微差别):
@decorator
def generator(): yield
正如Greg所说,有一些生成器理解,它可以很好地用于你可以使用它们,但如果你需要更多的逻辑,那么你所做的似乎是最恐怖的方式。只是Python语法总是使函数式编程非常笨拙。
您在评论中询问了有do
运算符的语言。 CoffeeScript和Haskell都有它。说实话,我并不是真的理解anything the Haskell docs say,但在CoffeeScript中,do
对于在闭包中创建值非常有用。
看一下这段代码(下面有一个解释)。
updateElementText = do ->
element = jQuery "#someElement"
return (newText) -> element.text newText
在JS中看起来像这样:
let updateElementText = function() {
let element = jQuery("#someElement");
return function(newText) { element.text(newText) };
}(); // Immediately-Invoked Function Expression (IIFE)
代码将updateElementText
分配给第3行返回的函数,该函数通过闭包引用element
。该元素仅由jQuery选择一次(在第2行),无论调用updateElementText
多少次来更新元素。另请注意,element
是隐藏的,因此只能由更新它的函数引用。