我正在尝试创建一个部分函数,但要使用动态参数将其存储为类属性并进行相应更改。类似于以下代码:
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()
当然,只有两个语句都将打印“ 1”,因为部分对象固定了参数。我发现的唯一选择是将属性更改为属性,然后使用设置器手动更改部分属性:
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
我想知道是否还有一种更“ pythonic” /有效的方法来执行此操作,因为除此解决方法外,我真的不需要使用属性。
答案 0 :(得分:2)
您可以使用lambda
而不是partial
进行参数的延迟(或通常称为“惰性”)评估,以便在调用函数之前不评估self.msg
:
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)
答案 1 :(得分:0)
仅存储对已传递函数的引用并立即构建调用有什么问题?即:
class Bar:
def __init__(self, msg):
self.msg = msg
self.foo = foo # a reference to foo, not needed here but used as an example
def foo_method(self, *args):
return self.foo(*args, msg=self.msg) # or just: foo(*args, msg=self.msg)
答案 2 :(得分:0)
我想到的最简单的方法就是构造一个字典,然后将其加双星传递给函数以进行解压缩。
类似的东西:
def some_func(msg, some_arg=None):
print("Hello world") # ignore the msg for now
call_args = {}
call_args['some_arg'] = 2 # single field
call_args.update({'msg': 1, 'stuff': [2,3,4]}) # multiple at once
some_func(**call_args)
现在,some_func将抛出TypeError,因为我们传递的args比函数需要的更多。您可以通过使函数在签名中接受** kwargs,减少您不希望使用的参数或其他方法来解决此问题。
现在,继续上一个会话:
call_args = {'msg': 'abc'} # let's get rid of those extra args
some_func(**call_args) # => prints 'Hello world'