在上下文管理器中部分应用函数(“with ..”)

时间:2012-03-27 16:41:06

标签: python metaprogramming contextmanager

基本上,我有一个api,它为Foo()类提供了一些方法Foo.bar(arg1,name)。

有没有办法在上下文管理器中将functools.partial对象应用于Foo.bar,例如:

x=Foo()
with my_argument(name="Something") as e:
    x.bar(arg1=5) # == x.bar(arg1=5, name="Something") in this context

我想知道除了猴子修补Foo.bar之外还有更优雅的方法吗?

编辑: 关键是,我有这样的代码:

model.addConstr(a, name="constraint_1")
model.addConstr(b, name="constraint_2")

如果没有额外的样板,下面的代码应该对'model'产生相同的调用:

with Arguments(name="constraint"):
    model.addConstr(a)
    model.addConstr(b)

3 个答案:

答案 0 :(得分:2)

我认为你不一定需要上下文管理器,你可以使用functools中的partial来代替:

from functools import partial
x=Foo()
_xbar = partial(x.bar, name="something")
_xbar(arg1=5)

如果您想“切换上下文”,只需重新标记_xbar

_xbar = partial(x.bar, name="some other thing")

答案 1 :(得分:2)

class Argumentor(object):
  def __init__(self, *args, **kwargs):
    self.args = args
    self.kwargs = kwargs

  def __enter__(self):
    return self

  def __exit__(self, exc_type, exc_val, exc_tb):
    pass

  def __call__(self, func, *args, **kwargs):
    newargs = args + self.args
    newkwargs = kwargs.copy()
    newkwargs.update(self.kwargs)
    return func(*newargs, **newkwargs)

def foo(num, name):
  print num, name

with Argumentor(name='bar') as f:
  f(foo, 42)

答案 2 :(得分:1)

不是那样,不。你的my_argument课程应该如何知道它与x.bar一起使用而没有你传递它?在这种情况下,__enter__()的{​​{1}}和__exit__()方法到底会做什么?

我不明白为什么你不只为my_argument制作一个functools.partial对象并使用它。