Python Forum
Python returns generator instead of None
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Python returns generator instead of None
#1
I have no clue why this is occurring. My class function isn't returning None regardless of how I write my code. Here's my search function below:

    def search(self, box):
        if len(self.truck.boxes) == 0:
            return None
        start = 0
        end = len(self.truck.boxes) - 1
        while end - start > 1:
            mid = (start + end) // 2
            if self.truck.boxes[end] < self.truck.boxes[start]:
                if self.truck.boxes[mid].volume() <= box.volume() and box.volume() <= self.truck.boxes[end].volume(): ##indent is okay?
                    start = mid
                elif self.truck.boxes[mid].volume() <= box.volume() and box.volume() >= self.truck.boxes[end].volume():
                    end = mid
                elif self.truck.boxes[mid].volume() > box.volume() and box.volume() >= self.truck.boxes[start].volume():
                    end = mid
                elif self.truck.boxes[mid].volume() > box.volume() and box.volume() <= self.truck.boxes[end].volume():
                    start = mid
            elif self.truck.boxes[end] > self.truck.boxes[start]:
                if self.truck.boxes[mid].volume() <= box.volume():
                    start = mid
                else:  #self.truck.boxes[mid].volume() > box.volume()
                    end = mid
            
        right = None
        if self.truck.boxes[start].volume() != box.volume() and self.truck.boxes[end] != box.volume():
            return None
        elif self.truck.boxes[start].volume() == box.volume():
            right = start
        elif self.truck.boxes[end].volume() == box.volume():
            right = end

        start = 0
        while right - start > 1:
            mid = (right + start) // 2
            if self.truck.boxes[mid].volume() == self.truck.boxes[right].volume():
                right = mid
            else:
                start = mid
                
        begin = 0
        if self.truck.boxes[start].volume() == box.volume():
            begin = start
        else:  # self.truck.boxes[right].volume() == box.volume():
            begin = right
            
        while self.truck.boxes[begin].volume() == box.volume():
            yield self.truck.boxes[begin]
            begin += 1
Particularly this snippet of the code here:

right = None
    if self.truck.boxes[start].volume() != box.volume() and self.truck.boxes[end] != box.volume():
        return None
    elif self.truck.boxes[start].volume() == box.volume():
        right = start
    elif self.truck.boxes[end].volume() == box.volume():
        right = end
I can assure (through my own testing) that the code should be returning None here when I input a box object whose volume is not found in the OrganizedTruck's list of boxes.

Just before the above snippet of code, self.truck.boxes[start].volume() and self.truck.boxes[end].volume() are NOT equal to the volume of the input box (I'm 99% sure this is true, I debugged via print functions), and therefore the first condition should be satisfied and the code should return None, right?

However, when I do run my code, my function returns some generator instead: <generator object OrganizedTruck.search at 0x00000272D1424258>

Why isn't my function returning None? I know for sure that that condition should be triggered, so I have no explanation for this other than Python is ignoring the condition completely...
Reply
#2
Every function containing the yield keyword is a generator.
Reply
#3
(Mar-08-2018, 10:44 PM)Gribouillis Wrote: Every function containing the yield keyword is a generator.

I see, then is there any way to simply return "None" instead of a generator?
Reply
#4
(Mar-08-2018, 11:11 PM)Tawnwen Wrote: is there any way to simply return "None" instead of a generator?
Remove the yield statement.
Reply
#5
You can also yield None.

For example, this returns as last element None:

def gen1():
    yield 1
    yield 2
    yield None

list(gen1())
Mixing yield and return in a function changes the behavior. When reaching the return statement, the generator closes and the return value is the value in the StopIteration Exception. Normal consumers don't capture the value.

def gen2():
    yield 1
    return 2
list(gen2())
In general return is used in a generator to stop the iteration at some condition.

def gen3(x):
    for i in range(x):
        if i > 10:
            return 'Value is bigger then 10'
        yield i

list(gen3(20))
To get the return value, you have to catch the exception.

def worker(x):
    gen = gen3(x)
    while True:
        try:
            value = next(gen)
        except StopIteration as val:
            print('StopIteration:', val)
            return
        yield value

list(worker(20))
A generator which yields the StopIteration value.

def gen4(x):
    gen = gen3(x)
    while True:
        try:
            yield next(gen)
        except StopIteration as e:
            yield e.value
            return

list(gen4(20))
Almost dead, but too lazy to die: https://sourceserver.info
All humans together. We don't need politicians!
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Annualised returns in python. Urgent request shivamdang 2 2,131 Apr-12-2020, 07:37 AM
Last Post: shivamdang
  Python function returns inconsistent results bluethundr 4 3,137 Dec-21-2019, 02:11 AM
Last Post: stullis
  why the generator expression after IF always returns True HenryJ 1 2,687 Feb-13-2018, 07:14 AM
Last Post: buran
  receive from a generator, send to a generator Skaperen 9 5,422 Feb-05-2018, 06:26 AM
Last Post: Skaperen
  Python Code Generator KatherineHov 11 8,792 Jul-27-2017, 10:04 AM
Last Post: MTVDNA
  Python object that returns tuples? alfredocabrera 1 2,865 Mar-27-2017, 12:27 PM
Last Post: Ofnuts

Forum Jump:

User Panel Messages

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