2016-06-20 7 views
0

У меня есть функция f, которая возвращает два параметра. После этой функции я использую первый параметр. Мне нужен второй, чтобы склеить вещи вместе с другой функцией g. Так что мой код будет выглядеть следующим образом:Скрыть вызовы после операции с помощью оператора

a, b = f() 
# do stuff with a 
g(b) 

Это очень повторяющееся, поэтому я полагал, что я мог бы использовать что-то вроде RAII подхода. Но, так как я не знаю, когда объекты будут умирать и моя главная цель состоит в том, чтобы избавиться от повторяющегося кода, я использовал with заявление:

with F() as a: 
    # do stuff with a 

Вот так. Я в основном создал объект F вокруг этой функции, поставляя функции __enter__ и __exit__ (и, очевидно, __init__).

Тем не менее, я все еще задаюсь вопросом, является ли это правильным "Pythonic" способом справиться с этим, поскольку инструкция with предназначена для обработки исключений. Особенно это функция __exit__ имеет три аргумента, которые я не использую в данный момент.

Редактировать (дальнейшие пояснения): Всякий раз, когда я звоню f() Мне НУЖНО что-то делать с b. Неважно, что произошло между ними. Я выразил это как g(b). И именно это я скрываю в заявлении. Поэтому программисту не нужно вводить g(b) снова и снова после каждого звонка f(), который может стать очень запутанным и запутанным, поскольку #do stuff with a может затянуться.

+0

* Является ли это * очень повторяющимися? Неясно, в чем проблема, или почему вы считали, что менеджер контекста является лучшим решением. Если вы используете этот код много, сделайте его функцией с параметрами 'a' и' b'. Если бит в середине изменяется, поэтому вы думаете, что не можете его извлечь, а затем добавьте новый параметр, который является функцией для вызова с 'a' перед вызовом' g' (обратите внимание, что функции являются первоклассными в Python). Не могли бы вы дать менее абстрактный пример того, чего вы пытаетесь достичь? Что делает 'g' * do *? – jonrsharpe

+1

Можете ли вы объяснить, как это повторяется в точности? Кроме того, как вы в настоящее время используете 'b' в своем заявлении? Лично я предпочитаю использовать 'with' для вещей, которые выглядят как ресурсы. Другая альтернатива - использование декораторов. – SuperSaiyan

+0

Что такое 'g'? Должна ли она произойти, если исключение будет выброшено? Если это не должно произойти, должна ли произойти какая-то другая очистка? – user2357112

ответ

1

Чуть более вещий способ сделать это было бы использовать contextlib модуль. Вы можете отказаться от развертывания собственного класса с функциями __enter__ и __exit__.

from contextlib import contextmanager 

def g(x): 
    print "printing g(..):", x 

def f(): 
    return "CORE", "extra" 

@contextmanager 
def wrap(): 
    a, b = f() 
    try: 
     yield a 
    except Exception as e: 
     print "Exception occurred", e 
    finally: 
     g(b) 
if __name__ == '__main__': 
    with wrap() as x: 
     print "printing f(..):", x 
     raise Exception() 

Выход:

$ python temp.py 
printing f(..): CORE 
Exception occurred 
printing g(..): extra 
+0

Я думаю, что вы застряли декоратор '@ contextmanager' в неправильной функции. – user2357112

+0

Да, это была проблема с копией. Исправлено, спасибо! – SuperSaiyan

+0

yep, вот что я хотел. Но если i (в будущем) нужно обрабатывать исключения, мне нужен мой собственный причудливый класс с функцией выхода и ввода, правильно? – hr0m

1

Для кого-то, кто читает ваш код (или вы через 6 месяцев), менеджер контекста, вероятно, будет подразумевать создание/инициализацию и закрытие/удаление ресурса, и я был бы очень осторожен в повторном назначении идиомы.

Вы можете использовать композицию, а не менеджером контекста:

def func(a, b): 
    # do stuff with a & optionally b 

def new_f(do_stuff): 
    a, b = f() 
    do_stuff(a, b) 
    g(b) 


new_f(func) 
+0

Это приятно, но, к сожалению, не вариант, так как мне нужно быть более общим. См. Это как сложный 'do_stuff', который не может быть обработан только одним fucntion – hr0m

+0

, вы всегда можете вывести несколько вызовов в одну функцию. Хорошо названные и хорошо документированные функции лучше, чем большие блоки кода. –