Python yield 语句 returns 每次都是相同的值
Python yield statement returns the same value every time
编辑:我想查看使用 next
语句的解决方案。
我正在访问一个天气应用程序 API,它 return 是一个 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"
}
]
}
这里是每天应该return一个元组的函数,但它没有。它保留 return 同一天的数据元组,即第一天。
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')
因为每次循环时都会启动生成器,而不是循环一个范围,只是迭代生成器:
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)
我建议将 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')]
您重新创建生成器 3 次,然后生成相同的第一个元素 3 次。在循环之前创建生成器。简单胜于复杂。
x = forecast(daily_return))
for i in range(3):
print(next(x))
编辑:我想查看使用 next
语句的解决方案。
我正在访问一个天气应用程序 API,它 return 是一个 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"
}
]
}
这里是每天应该return一个元组的函数,但它没有。它保留 return 同一天的数据元组,即第一天。
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')
因为每次循环时都会启动生成器,而不是循环一个范围,只是迭代生成器:
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)
我建议将 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')]
您重新创建生成器 3 次,然后生成相同的第一个元素 3 次。在循环之前创建生成器。简单胜于复杂。
x = forecast(daily_return))
for i in range(3):
print(next(x))