【问题标题】:Python yield statement returns the same value every timePython yield 语句每次都返回相同的值
【发布时间】:2020-09-30 06:40:29
【问题描述】:

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

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')

【问题讨论】:

  • 避免重新创建生成器,在循环之前创建x = forecast(daily_return)); for i in range(3): print(next(x))

标签: python yield next


【解决方案1】:

因为您每次循环时都在启动生成器,而不是循环一个范围,所以只需迭代生成器:

for sunrise, sunset in forecast(daily_return):
    print(sunrise, sunset)

如果你只想要前 3 个,你可以用一个范围压缩它或使用 itertools.islice @cs95 所示:

for sunrise, sunset, _ 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 sunrise, sunset in islice(forecast_gen, 3):
    print(sunrise, sunset)

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      【解决方案3】:

      我建议将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')]
      

      【讨论】:

      • 我喜欢你对islice 的实现,我只是想避免从另一个库导入。
      • @Jab 很高兴您的一天充实了一个islice
      • 我知道你在那里做了什么。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-09
      相关资源
      最近更新 更多