Dynamically define functions (methods) in Python

I'm addicted to it, so I hope it helps someone.

** What you are trying to do **: Define a function that dynamically displays three different paths

The value of t is the last value processed by for because the inside of def func is evaluated when the function is actually called.

>>> path_freq = [{"path": "/pickup/6162449", "freq": 1, "name": "a"}, {"path": "/pickup/6162466", "freq": 1, "name": "b"}, {"path": "/pickup/6162461", "freq":1, "name": "c"}]
>>> task_list = {}
>>> for t in path_freq:
...   def func():
...     print(t)
...   task_list.update({func: t['path']})
...
>>> task_list
{<function func at 0x101184848>: '/pickup/6162461', <function func at 0x101184938>: '/pickup/6162466', <function func at 0x1011848c0>: '/pickup/6162449'}
>>> for k,v in task_list.items():
...   k()
...
{'path': '/pickup/6162461', 'freq': 1, 'name': 'c'}
{'path': '/pickup/6162461', 'freq': 1, 'name': 'c'}
{'path': '/pickup/6162461', 'freq': 1, 'name': 'c'}

Try something similar in Ruby

[2] pry(main)> path_freq = [{"path" => "/pickup/6162449", "freq" => 1, "name" => "a"}, {"path" => "/pickup/6162466", "freq" => 1, "name" => "b"}, {"path" => "/pickup/6162461", "freq" => 1, "name" => "c"}]
=> [{"path"=>"/pickup/6162449", "freq"=>1, "name"=>"a"},
 {"path"=>"/pickup/6162466", "freq"=>1, "name"=>"b"},
 {"path"=>"/pickup/6162461", "freq"=>1, "name"=>"c"}]
[3] pry(main)> path_freq.each do |t|
[3] pry(main)*   define_method :hoge do
[3] pry(main)*     puts t
[3] pry(main)*   end
[3] pry(main)*   task_list.merge!({hoge => t})
[3] pry(main)* end
{"path"=>"/pickup/6162449", "freq"=>1, "name"=>"a"}
{"path"=>"/pickup/6162466", "freq"=>1, "name"=>"b"}
{"path"=>"/pickup/6162461", "freq"=>1, "name"=>"c"}
=> [{"path"=>"/pickup/6162449", "freq"=>1, "name"=>"a"},
 {"path"=>"/pickup/6162466", "freq"=>1, "name"=>"b"},
 {"path"=>"/pickup/6162461", "freq"=>1, "name"=>"c"}]
[4] pry(main)> task_list
=> {nil=>{"path"=>"/pickup/6162461", "freq"=>1, "name"=>"c"}}
[5] pry(main)> hoge
{"path"=>"/pickup/6162461", "freq"=>1, "name"=>"c"}
=> nil

I thought that Python and Ruby have similar language specifications, but I don't think that can be said unconditionally. Methods are treated as Objects in Python, but not in Ruby. In the case of Ruby, when the hoge method is defined by define_method, it is defined as the method of main Object in this example. You can't put the hoge method as an Object in an array. By the way, the reason why nil is included in the key of task_list is that the return value of puts is nil in Ruby.

Then try defining the method in another way. Trying to add a method to class with setaddr in Python, the same behavior.

>>> class Test(): 
...   pass
>>> path_freq = [{"path": "/pickup/6162449", "freq": 1, "name": "a"}, {"path": "/pickup/6162466", "freq": 1, "name": "b"}, {"path": "/pickup/6162461", "freq":
1, "name": "c"}]
>>> task_list = []
>>> for t in path_freq:
...   def func():
...     print(t)
...   setattr(Test, t['name'], func)
...   task_list.append(func)
...
>>> for f in task_list:
...   f()
...
{'path': '/pickup/6162461', 'freq': 1, 'name': 'c'}
{'path': '/pickup/6162461', 'freq': 1, 'name': 'c'}
{'path': '/pickup/6162461', 'freq': 1, 'name': 'c'}
>>> for t in path_freq:
...   def func(self):
...     print(t)
...   setattr(Test, t['name'], func)
...
>>> Test().a()
{'path': '/pickup/6162461', 'freq': 1, 'name': 'c'}
>>> Test().b()
{'path': '/pickup/6162461', 'freq': 1, 'name': 'c'}
>>> Test().c()
{'path': '/pickup/6162461', 'freq': 1, 'name': 'c'}

I tried to pass the value of List by the default value of the argument because the signature of the function is not lazy evaluated.

>>> path_freq = [{"path": "/pickup/6162449", "freq": 1, "name": "a"}, {"path": "/pickup/6162466", "freq": 1, "name": "b"}, {"path": "/pickup/6162461", "freq":1, "name": "c"}]
>>> task_list = {}
>>> for t in path_freq:
...   def func(path=t['path']):
...     print(path)
...   task_list.update({func: t['path']})
...
>>> for k,v in task_list.items():
...   k()
...
/pickup/6162461
/pickup/6162466
/pickup/6162449

:+1:

Recommended Posts

Dynamically define functions (methods) in Python
[Python3] Dynamically define global variables in functions
Dynamically call methods in Python
String object methods in Python
Dynamically import scripts in Python
Overriding library functions in Python
Python functions learned in chemoinformatics
Dynamically load json type in python
Python functions
Using global variables in python functions
Easily use your own functions in Python
Pharmaceutical company researchers summarized functions in Python
Private methods and fields in python [encryption]
New features in Python 3.4.0 (3)-Single-dispatch generic functions
How to dynamically zero pad in Python
Summary of built-in methods in Python list
Quadtree in Python --2
Python in optimization
CURL in python
Metaprogramming in Python
Python 3.3 in Anaconda
Geocoding in python
SendKeys in Python
Meta-analysis in Python
Unittest in python
Epoch in Python
Discord in Python
Sudoku in Python
DCI in Python
quicksort in python
N-Gram in Python
Programming in python
Plink in Python
Constant in python
#Python basics (functions)
Lifegame in Python.
FizzBuzz in Python
Sqlite in python
[Beginner] Python functions
StepAIC in Python
LINE-Bot [0] in Python
Csv in python
Disassemble in Python
Reflection in Python
Constant in python
nCr in Python.
format in python
Scons in Python3
Puyo Puyo in python
python in virtualenv
PPAP in Python
Python Easy-to-use functions
Quad-tree in Python
Python basics: functions
Reflection in Python
Chemistry in Python
Hashable in python
DirectLiNGAM in Python
LiNGAM in Python
Flatten in python
flatten in python