Частичное применение функций внутри контекстного менеджера («с ..») - PullRequest
0 голосов
/ 27 марта 2012

По сути, у меня есть 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")

И без дополнительного шаблона следующий код должен вызывать те же вызовы для «модели»:

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

Ответы [ 3 ]

2 голосов
/ 27 марта 2012

Не думаю, что вам обязательно нужен менеджер контекста, вместо этого вы можете использовать part из functools:

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

Если вы хотите «переключить контекст», просто переопределите _xbar:

_xbar = partial(x.bar, name="some other thing")
2 голосов
/ 27 марта 2012
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)
1 голос
/ 27 марта 2012

Не так, нет. Как ваш класс my_argument должен знать, что он предназначен для работы с x.bar без вашего участия? Что именно будут делать __enter__() и __exit__() методы my_argument в этой ситуации?

Я не понимаю, почему вы не просто создаете functools.partial объект для x.bar и используете его.

...