python yield语句每次都返回相同的值

时间:2020-06-10 18:23:39

标签: python yield next

编辑:我想使用next语句查看解决方案。 我正在访问一个天气应用程序API,该API返回一个json对象,该对象的一部分信息是日出和日落的每日时间,以下是其内容(三天):

my_dict = {
"daily": [
    {
      "dt": "2020-06-10 12:00:00+01:00",
      "sunrise": "2020-06-10 05:09:15+01:00",
      "sunset": "2020-06-10 19:47:50+01:00"
    },
    {
        "dt": "2020-06-11 12:00:00+01:00",
        "sunrise": "2020-06-11 05:09:11+01:00",
        "sunset": "2020-06-11 19:48:17+01:00"
    },
    {
      "dt": "2020-06-12 12:00:00+01:00",
      "sunrise": "2020-06-12 05:09:08+01:00",
      "sunset": "2020-06-12 19:48:43+01:00"
    }
]
}

这是每天应该返回一个元组的函数,但不是。它会在第一天的第一天不断返回元数据。

daily_return = my_dict['daily']


def forecast(daily_return):
    # daily_return is a list
    for day in daily_return:
        # day becomes a dict
        sunrise = day['sunrise']
        sunset = day['sunset']
        yield sunrise, sunset

for i in range(3):
    print(next(forecast(daily_return)))

这是输出:

('2020-06-10 05:09:15+01:00', '2020-06-10 19:47:50+01:00')
('2020-06-10 05:09:15+01:00', '2020-06-10 19:47:50+01:00')
('2020-06-10 05:09:15+01:00', '2020-06-10 19:47:50+01:00')

3 个答案:

答案 0 :(得分:6)

因为每次循环时都要启动生成器,而不是循环范围,而只是迭代生成器:

for rise, set in forecast(daily_return):
    print(rise, set)

如果只希望前3个,则可以按一定范围压缩它,或使用itertools.islice,如@ cs95所示:

for rise, set, _ in zip(forecast(daily_return), range(3)):
    print(rise, set)

如果必须使用next,则在循环外启动生成器:

gen = forecast(daily_return)
for i in range(3):
    print(next(gen))

您也可以使用operator.itemgetter来实现相同的功能,而不是使用自定义功能:

from operator import itemgetter
from itertools import islice

forecast_gen = map(itemgetter('sunrise', 'sunset'), daily_return)

for rise, set in islice(forecast_gen, 3):
    print(rise, set)

答案 1 :(得分:2)

我建议将forecast转换为对单个条目进行操作的函数。然后,您可以调用map以获得迭代器,并在其上调用next

def forecast(day):
    return day['sunrise'], day['sunset']

it = map(forecast, daily_return)
print(next(it))
# ('2020-06-10 05:09:15+01:00', '2020-06-10 19:47:50+01:00')

如果要从迭代器中获得X个条目,请使用islice

from itertools import islice
list(islice(map(forecast, daily_return), 3))
# [('2020-06-10 05:09:15+01:00', '2020-06-10 19:47:50+01:00'),
#  ('2020-06-11 05:09:11+01:00', '2020-06-11 19:48:17+01:00'),
#  ('2020-06-12 05:09:08+01:00', '2020-06-12 19:48:43+01:00')]

答案 2 :(得分:0)

您将生成器生成3次,然后将相同的第一个元素生成3次。在循环之前创建生成器。简单胜于复杂。

SELECT ti.*
FROM   transaction t
JOIN   transaction_item ti ON ti.transaction_id = t.transaction_id -- ?
WHERE  t.pos_transaction_id = 4220
AND    t.location_id = 1674
AND    t.transaction_date = '2020-05-08';
AND    NOT EXISTS (
   SELECT FROM transaction_item tx
   WHERE  tx.transaction_id = t.transaction_id
   AND    tx.amount < 2);