0

I'm trying to learn more about generator functions in Python. To my knowledge, generator functions don't fully return until there are no more yield calls, so a stack frame exists in the generator returned by the function.

Stack frames should have references to a callable function, so my question is: how can I get that callable function from the generator?

When running the code below, I have a generator function, test().

def test():
 for i in range(10):
 yield i
generator = test()

In this example, is there any way to get the callable function test() from generator?

After looking at this answer, it seems like CPython keeps track of some of these like generator.frame and generator.code, however, I can't seem to convert those objects into functions.

I need the callable function. Something like this:

func = generator.something_special
new_generator = func()
asked Oct 20, 2022 at 2:40
5
  • 2
    Your code never tried to print the stack from within the test() function so it's never going to be in the current stack - it literally yielded the execution back to its caller (i.e. main()). If you want a bit more detail this thread dives into how generators work. Commented Oct 20, 2022 at 2:50
  • "Where are the stack frames" - in memory, but not in the current stack. They are only in the stack while they are active. Commented Oct 20, 2022 at 3:40
  • @kaya3 Ok, I see. Is there any way to get the names of the functions that are in this memory but not active? Commented Oct 20, 2022 at 3:42
  • Not unless you have some general way of getting all of the objects which exist in memory, even those which you don't have access to via references. What is the reason that you want access to inactive stack frames? Commented Oct 20, 2022 at 3:44
  • @kaya3 I've tried to update my question to better explain what I'm trying to say. What I really want to do is get a function name from a generator after it has been returned. Commented Oct 20, 2022 at 3:50

1 Answer 1

1

You can use the __name__ attribute to get the name of the original function then access it inside locals provided it's still in scope.

def test():
 for i in range(10):
 yield i
generator = test()
print(list(generator)) 
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
func_name = generator.__name__ 
new_generator = locals()[func_name]()
print(func_name, list(new_generator)) 
# test [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
answered Oct 20, 2022 at 4:26
Sign up to request clarification or add additional context in comments.

2 Comments

I found that in some cases (ie: when inside a function), you need to use globals() instead of locals(). However, using globals() will make it always work regardless of scope.
@MichaelM.Yeah if the function is outside of the scope locals() won't pick it up but globals() usually will. Heads up btw using globals and locals gets risky fast. I recommend doing some googling on some of the pitfalls of using them.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.