Могу ли я использовать Python с оператором для условного исполнения?

StackOverflow https://stackoverflow.com/questions/4314338

  •  29-09-2019
  •  | 
  •  

Вопрос

Я пытаюсь написать код, который поддерживает следующую семантику:

with scope('action_name') as s:
  do_something()
  ...
do_some_other_stuff()

Область, среди прочего (настройка, очистка) должна решить, должен ли этот раздел работать.
Например, если пользователь настроил программу обойти 'action_name', чем, после Scope () оценивается DO_SOME_OTHER_STUFF (), будет выполняться без вызова DO_SOMETHETION ().
Я попытался сделать это с помощью этого диспетчера контекста:

@contextmanager
def scope(action):
  if action != 'bypass':
    yield

но получил RuntimeError: generator didn't yield Исключение (когда action является 'bypass').
Я ищу способ поддержки этого, не возвращаясь к более подробному дополнительной реализации:

with scope('action_name') as s:
  if s.should_run():
    do_something()
    ...
do_some_other_stuff()

Кто -нибудь знает, как я могу этого добиться?
Спасибо!

PS Я использую Python2.7

РЕДАКТИРОВАТЬ:
Решение не обязательно нужно полагаться на with заявления. Я просто не знал точно, как выразить это без него. По сути, я хочу что -то в форме контекста (поддерживающая настройка и автоматическая очистка, не связанная с содержащейся логикой) и позволяя для условного выполнения на основе параметров, передаваемых методу настройки и выбранных в конфигурации.
Я также думал о возможном решении с использованием декораторов. Пример:

@scope('action_name') # if 'action_name' in allowed actions, do:
                      #   setup()
                      #   do_action_name()
                      #   cleanup()
                      # otherwise return
def do_action_name()
  do_something()

Но я не хочу обеспечить слишком много внутренней структуры (то есть, как код делится на функции) на основе этих областей.
У кого -нибудь есть творческие идеи?

Это было полезно?

Решение

Вы пытаетесь изменить ожидаемое поведение базовой языковой конструкции. Это никогда не будет хорошей идеей, это просто приведет к путанице.

Нет ничего плохого в вашей обходе, но вы можете немного упростить это.

@contextmanager 
def scope(action): 
  yield action != 'bypass'

with scope('action_name') as s: 
  if s: 
    do_something() 
    ... 
do_some_other_stuff() 

Ваш scope вместо этого может быть класс, чьи __enter__ Метод возвращает либо полезный объект, либо None И это будет использоваться таким же образом.

Другие советы

Следующее, кажется, работает:

from contextlib import contextmanager

@contextmanager
def skippable():
    try:
        yield
    except RuntimeError as e:
        if e.message != "generator didn't yield":
            raise

@contextmanager
def context_if_condition():
    if False:
        yield True

with skippable(), context_if_condition() as ctx:
    print "won't run"

Соображения:

  • Нужен кто -то, чтобы придумать лучшие имена
  • context_if_condition нельзя использовать без skippable Но нет никакого способа обеспечить соблюдение/удалить избыточность
  • Он мог бы уловить и подавить время выполнения от более глубокой функции, чем предполагалось (настраиваемое исключение может помочь там, но это все еще делает всю конструкцию Местье)
  • Это не более яснее, чем просто использовать версию @mark Ransom

Я не думаю, что это можно сделать. Я попытался внедрить менеджер контекста в качестве класса, и просто нет возможности сила блок, чтобы поднять исключение, которое впоследствии будет зажат __exit__() метод.

У меня такой же вариант использования, как и вы, и наткнулся на условная библиотека Чтобы кто-то был полезно разработан в то время, так как вы разместили свой вопрос.

С сайта его использование как:

with conditional(CONDITION, CONTEXTMANAGER()):
    BODY()
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top