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