Dot notation with clousures in Python

Let’s dive some deeply in closures in Python . Look at this example:

def func_as_object():
    def echo_foo():
        print('run echo_foo() func')

    def replace():
        pass

    replace.echo_bar = echo_foo
    return replace


f = func_as_object()

f.echo_bar()  # prints 'run echo_foo() func'

What happens in this code? What is the construction - replace.echo_bar ?

Okay, okay, let’s start from another side. Here is another code:

import types

mod = types.ModuleType('my_module')

def my_func():
    print('Hello from my_func in my_module')

mod.my_func = my_func

mod.my_func()  # prints 'Hello from my_func in my_module'

They are looks similar, and that is! types.ModuleType - it is an class which represent python module object. When you import some module in python script, python create instance of this class like in example above. So, expression mod = types.ModuleType('my_module') is equal to import my_module as mod. This is the first step of explanation. The second - what happens in this string? mod.my_func = my_func. types.ModuleType class allows you to create methods of it’s instances by assign any function. To create new method for mod we can simply write:

mod.new_method = any_func

This is becomes possible because types.ModuleType allows you to use methods getattr() and setattr().

Now then going to our first example with closure. When python sees construction in enclosing or local scope like:

def foo():
	def something():
		print('something')
	def replace():
		pass

	replace.to = something

he automatically create instance of types.ModuleType named replace, and then it has the same behavior like we talking before.

Note again, this is working only in local or enclosing scope, not global.

Why is it needed? Actually, I don’t quite understand. If you can give me any useful examples of this feature, please, feel free to contact me