Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Yielding ahead of time
#1
Question 
I was making a function that could output the results one by one with yield or return all results in a list. I have everything in the right indention, but it always. Does anyone know the reason why? Confused

I am using Python 3.9 if that helps.
def get_ep_info(iter=False):
		ep_list_info = list()

		ep_nums = [1,2,3,4,5]
		for ep_num in ep_nums:
			if iter is True:
				print("true")
				yield ep_num
			elif iter is False:
				print("false")
				ep_list_info.append(ep_num)

		if iter is False:
			print("false")
			return ep_list_info

a = get_ep_info()
print(a)
Output:
<generator object get_ep_info at 0x0000022A5D048BA0>
Reply
#2
Containing yield makes a function a generator. And since the yield forces the function to be a generator you need to use next or for to get the values and you cannot use return in the function. You could write your function like this:
def get_ep_info(iter=False):
        ep_list_info = list()
 
        ep_nums = [1,2,3,4,5]
        for ep_num in ep_nums:
            if iter is True:
                print("true")
                yield ep_num
            elif iter is False:
                print("false")
                ep_list_info.append(ep_num)
 
        if iter is False:
            print("false")
            yield ep_list_info  #<- Change from return to yeild
 
a = next(get_ep_info())
print(a)
But it makes far more sense to leave it a generator and use list() to create a list of the returned values.
def get_ep_info():
    for ep_num in [1,2,3,4,5]:
        yield ep_num
 
a = list(get_ep_info())
print(a)
This is less likely to result in uncontrolled laughter or swearing when people try to use your code
Daring_T likes this post
Reply
#3
See if this is what you wanted:

def get_ep_info(iterator=False):
		ep_list_info = list()
		ep_nums = [1,2,3,4,5]

		for ep_num in ep_nums:
			ep_list_info.append (ep_num)
 
		if iterator is False:
			return ep_list_info
		else :
			return iter(ep_list_info)
 
a = get_ep_info(True)
print(next (a), next (a))
Reply
#4
While this works for the original example:
def get_ep_info(iterator=False):
        ep_list_info = list()
        ep_nums = [1,2,3,4,5]
 
        for ep_num in ep_nums:
            ep_list_info.append (ep_num)
  
        if iterator is False:
            return ep_list_info
        else :
            return iter(ep_list_info)
  
a = get_ep_info(True)
print(next (a), next (a))
It does not create code that acts like a generator. Regardless of the iterator flag all the results are created immediately and the advantages of using a generator are lost. It is better to act like a generator and use something like list() to create a collection from the generator results. That allows getting the benefits of a generator or getting a collection depending on you need.
Reply
#5
Thanks to everyone how replyed. This is the code I think I am going to use. I just have never across this before where yielding overrides the return statement. The ep_nums[] is a placeholder for the function that I was working on when I ran into this issue.

def get_ep_info_iter():
	# This is placeholder data
	ep_nums = [1,2,3,4,5]
	for ep_num in ep_nums:
			yield ep_num

get_ep_info = lambda : list(get_ep_info_iter())

a = get_ep_info_list()
print(a)
Reply
#6
Lightbulb 
Quote:Containing yield makes a function a generator. And since the yield forces the function to be a generator you need to use next or for to get the values and you cannot use return in the function. You could write your function like this:

def get_ep_info(iter=False):
        ep_list_info = list()
  
        ep_nums = [1,2,3,4,5]
        for ep_num in ep_nums:
            if iter is True:
                print("true")
                yield ep_num
            elif iter is False:
                print("false")
                ep_list_info.append(ep_num)
  
        if iter is False:
            print("false")
            yield ep_list_info  #<- Change from return to yield

a = next(get_ep_info())
print(a)
But it makes far more sense to leave it a generator and use list() to create a list of the returned values.
def get_ep_info():
    for ep_num in [1,2,3,4,5]:
        yield ep_num

a = list(get_ep_info())
print(a)
This is less likely to result in uncontrolled laughter or swearing when people try to use your code

Thanks for the reply, I never knew that list() could take in generators. That's great to know instead of doing a comprehension list Cool.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  logging messages ahead of print messages vindo 6 3,140 Jun-18-2019, 02:45 PM
Last Post: vindo
  Issues with async and yielding from API GSerum 1 2,105 Dec-18-2018, 08:37 PM
Last Post: nilamo

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020