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 path
s
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