0

I am trying to findout why I get a generator instead of getting item printed since the second time I instanciate the Scrape() i did not request for a yielded result which I find strange that it returns one.

I would like to avoid this assuming it is possible and would like to know why this happens. See comment in code if you find it hard to understand or comment out the very last for loop

This is a working code that can be tested in python 2.7 without modification. The code a simulation of my actual problem which I didn't know I could recreate with a more simpler example compared to the original code.

    from Tkinter import *
import ttk
import threading

class Gui(ttk.Frame):
    def __init__(self, master):
        ttk.Frame.__init__(self, master)
        self.master = master

        self.var = BooleanVar()
        self.numbers = IntVar()

        self.var.set(False)
        varbox = ttk.Checkbutton(self.master, text="On/OFF", variable=self.var, onvalue=True)
        varbox.pack()

        btn = Button(self.master, text="Start", command=self.start_scan)
        btn.pack()
        entry = Entry(self.master, textvariable=self.numbers) # normally user would enter a number for now we assume 100
        entry.pack()
        self.numbers.set(25)


    def start_scan(self):
        # start scan with a thread
        true_here = self.var.get()  # let us say this is True value
        numbers = self.numbers.get()
        t = ThreadIt(true_here, numbers) # gave thread True, 100
        t.start()


class Scrape(object):
    def __init__(self, numbers):
        self.numbers = numbers
        if self.numbers < 5:
            self.numbers = 20

    def do_stuff(self, var=False):

        # do things to change the world
        for i in range(2, self.numbers): #  -> 99
            if var:
                yield i * 20 # increase the number to we can recall this function
            else:
                print i

class ThreadIt(threading.Thread):
    def __init__(self, var, numbers):
        super(ThreadIt, self).__init__()
        self.var = var
        self.numbers = numbers

    def run(self):
        foo = Scrape(self.numbers)
        result = foo.do_stuff(var=self.var)  # since numbers is 25 this would yield from 2 to 24 as var is sent to TRUE

        if result: # if var above is false below wouldn't have happen
            for i in result:
                yielded = Scrape(i)
                print yielded , "foo"  # prints something line: <__main__.Scrape object at 0x112da4d90>

                res = yielded.do_stuff(var=False)

                print res # suppose no be None because its not suppose to yield since var is False but it prints generator as below
                # <generator object do_stuff at 0x10eef1aa0>
                for i in res: # this is not suppose to be a generator (Generator was done in result)
                    print i
                print "Finished"




root = Tk()
app = Gui(root)
root.mainloop()
root.destroy()
Jide Koso
  • 415
  • 5
  • 17
  • 4
    Calling a generator returns a generator object., it does not execute it! It only yields if you call `next()` or `send()` on the generator object, either directly or indirectly, like in a `for` loop. – cdarke Jan 10 '16 at 10:19

1 Answers1

1

I think you would benefit greatly from reading this answer

For your specific case, yielded = Scrape(i) indeed creates a object of type Scrape. And yielded.do_stuff(var=False) returns a generator because the yield statement is used in it's definition. Since var is False, it won't generate any element though and will just execute the line print i until exhaustion of the for loop.

But yeah, takes the time to read the first link I gave, it's beautiful

Community
  • 1
  • 1
Benoit Seguin
  • 1,937
  • 15
  • 21