Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python yield statement returns the same value every time

EDIT: I want to see the solution using the next statement. I am accessing a weather app API that returns a json object, a part of the information of that object is the daily time of sunrise and sunset, here is its content (for three days):

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"
    }
]
}

And here is the function that should return a tuple per day, but it does not. It keeps returning a tuple of data for the same day, the first day.

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

And here is the output:

('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')
like image 384
Mehdi Rezzag Hebla Avatar asked Dec 11 '25 17:12

Mehdi Rezzag Hebla


1 Answers

Because you're initiating the generator every time you loop instead of looping a range just iterate the generator:

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

If you only want the first 3 you can zip it with a range or use itertools.islice as @cs95 has shown:

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

If you must use next then initiate the generator outside the loop:

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

You can also use operator.itemgetter to achieve this same functionality instead of your custom function:

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)
like image 111
Jab Avatar answered Dec 13 '25 06:12

Jab



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!