Issue
I'm trying to create a partial function but with dynamic arguments that are stored as class attributes and changed accordingly. Something like the following code:
from functools import partial
def foo(*args, msg):
print(msg)
class Bar:
def __init__(self, msg):
self.msg = msg
self.functions = dict()
self.functions['foo'] = partial(foo, msg=self.msg)
def foo_method(self, *args):
return self.functions['foo'](*args)
b =Bar('1')
b.foo_method()
b.msg = '2'
b.foo_method()
Only, of course, both statements will print '1' as the partial object fixes the arguments. The only alternative I found was changing the attribute to a property and manually changing the partial attributes with the setter:
class Bar:
def __init__(self, msg):
self._msg = None
self.functions = dict()
self.functions['foo'] = partial(foo)
self.msg = msg
def foo_method(self, *args):
return self.functions['foo'](*args)
@property
def msg(self):
return self._msg
@msg.setter
def msg(self, msg):
self._msg = msg
self.functions['foo'].keywords['msg'] = msg
I would like to know if there is a more "pythonic" / efficient way to do this, since I really don't need to use properties except for this workaround.
Solution
You can use lambda
instead of partial
for deferred (or often referred to as "lazy") evaluation of the arguments, so that self.msg
is not evaluated until the function is called:
class Bar:
def __init__(self, msg):
self.msg = msg
self.functions = dict()
self.functions['foo'] = lambda *args: foo(*args, msg=self.msg)
def foo_method(self, *args):
return self.functions['foo'](*args)
Answered By - blhsing
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.