0

Is there any way that a function can be called once and then return data mutliple times at distinct times?

For example, suppose I had the following code:

def do_something():
    for i in range(1, 10):
        return 1

However, I want to be able to return more than one piece of data from a single function call, but at asynchronous times, is this possible?


For context, I have a program that generates word documents, converts them into pdfs and then combines them into a single pdf document. I want to be able to call an external function from the GUI to create the documents, and then display a progress bar that displays the current progress through the function.


Edit:

I am already aware of the yield function. I thought my specific problem at the bottom of the question would help. To be clearer, I am looking for is a way to return multiple values from a function and cause a different event for each value returned. Although it may be a poor example, what I want is to be able to do is something similar to a .then(){} in Javascript, but be able to perform the .then(){} using multiple returned values

Ronikos
  • 437
  • 1
  • 6
  • 18
  • 1
    Yes, there is something for exactly that: `yield` http://stackoverflow.com/questions/231767/what-does-the-yield-keyword-do – Iluvatar Dec 05 '16 at 17:36
  • No `yield` you have to call again and again. He want it to be called single time. – harshil9968 Dec 05 '16 at 17:37
  • 1
    @harshil9968 generators need to be called once. You store the iterator and then call the **iterator** again and again. This is what the for loop semantics does. Calling the function repeatedly would cause the iterator to lose state and start from the beginning. – bashrc Dec 05 '16 at 17:41
  • Just what do you mean by "at asynchronous times"? Do you mean when asked, which is what a generator with `yield` or an iterator does? Do you mean at pre-determined times, which could be done with a separate thread with a timer sending messages? Do you mean at pre-determined circumstances other than times, which may also be done with sending messages, depending on the circumstances or perhaps more simply with a callback function? Do you mean something else? – Rory Daulton Dec 05 '16 at 17:43

3 Answers3

1

yield is the thing as mentioned by almost everyone for returning or getting multiple values from a function.

Having read your problem statement. Here is the solution I would devise for you.

Create a function to update status bar, the value of status bar would be fetched from a global variable. So global x=0 at starting, and in the update function it will first update the x = x+1 then after that it will increment the status bar.

def do_something():
    for i in range(1, 10):
        # fetch and perform operation on that Doc for PDF
        update_status_bar()
harshil9968
  • 3,254
  • 1
  • 16
  • 26
0

You want a generator:

def do_something():
    for i in range(1,10):
        yield i

nums = do_something()

Each time you call next on nums, the body of do_something will continue executing up to the next yield statement, at which point it returns that value.

>>> print next(nums)   # Outputs 1
>>> print next(nums)   # Outputs 2
>>> ...
chepner
  • 497,756
  • 71
  • 530
  • 681
  • Have you read his problem statement. I don't think it will solve his problem. – harshil9968 Dec 05 '16 at 17:38
  • It's halfway there. He needs a generator, but it isn't going to magically call itself at random intervals to provide values to an unspecified consumer. – chepner Dec 05 '16 at 17:50
  • Thanks for your answer but I was already aware of the `yield` function. I thought my specific problem at the bottom of the question would help, what I am looking for is a way to return multiple values from a function and cause a different event for each value returned – Ronikos Dec 05 '16 at 17:53
  • Functions don't work that way. For something like a progress bar, *something* is calling a function at regular intervals to find out how much progress has been made, and calling some sort of screen update function using the result. Your question as asked is too broad to answer. – chepner Dec 05 '16 at 17:55
  • @Ronikos kindly have a look at my answer. – harshil9968 Dec 05 '16 at 17:59
0

You are looking for generators.

Instead of returning you yield (read What does the "yield" keyword do in Python?) from your function.

def do_something():
    for i in range(1, 10):
        yield i

If you want this function to be called repeatedly you will need to have a wrapper that calls this function repeatedly. Somewhat similar to:

def worker():
    for i in do_something():
       UpdateProgress(i)
       sleep(prgressInterval)

    thread = Thread(target=worker)
    thread.start()
Community
  • 1
  • 1
bashrc
  • 4,725
  • 1
  • 22
  • 49
  • Thanks for your answer but I was already aware of the `yield` function. I thought my specific problem at the bottom of the question would help, what I am looking for is a way to return multiple values from a function and cause a different event for each value returned – Ronikos Dec 05 '16 at 17:53