0

It might be a silly question, but I'm new to Python. I would like to understand how the following segment of code is possible.

class test:

    def main_method(self):

        variable = 10; 

        def sub_method(input):

            return input * variable

        self.result = sub_method

obj = test()

obj.main_method()

print(obj.result(4)) 

Output:

40

My question:

When I execute obj.result(4), how does self.result, being an instance variable that stores sub_method, has access to the scope of main_method and the value of variable without executing main_method again?

Thank you very much.

3
  • 2
    Because sub_method keeps the state of the free variables along with it. Python supports closures Commented May 23, 2017 at 23:26
  • I've never heard about it. I'm going to check it out. Thank you Commented May 23, 2017 at 23:31
  • Also, terminology nitpick: main_method just a method, not a class method. Commented May 23, 2017 at 23:39

1 Answer 1

1

This is possible because Python functions support closures:

Operationally, a closure is a record storing a function[a] together with an environment:[1] a mapping associating each free variable of the function (variables that are used locally, but defined in an enclosing scope) with the value or reference to which the name was bound when the closure was created.

Indeed, in Python, it is easy to introspect on this. Running your code...

In [2]: class test:
   ...:
   ...:     def main_method(self):
   ...:
   ...:         variable = 10;
   ...:
   ...:         def sub_method(input):
   ...:
   ...:             return input * variable
   ...:
   ...:         self.result = sub_method
   ...:
   ...: obj = test()
   ...:
   ...: obj.main_method()
   ...:

In [3]: obj.result
Out[3]: <function __main__.test.main_method.<locals>.sub_method>

Basically, each function carries around references to it's free variables:

In [6]: obj.result.__closure__
Out[6]: (<cell at 0x10448ff78: int object at 0x100214990>,)

In [7]: obj.result.__closure__[0].cell_contents
Out[7]: 10

And even the names of it's free variables are introspectable:

In [8]: obj.result.__code__.co_freevars
Out[8]: ('variable',)

In Python, a function is just another kind of object.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

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.