Python - приносить и поднимать исключения - PullRequest
0 голосов
/ 13 декабря 2018

Я пытаюсь написать функцию, которая выдает две переменные, а также вызывает исключение на основе условия.Вот минимальный пример:

def func():
  var1 = 0
  var2 = 1
  yield var1, var2
  if not var1 > var2:
    raise Exception(var1,var2)
var1, var2 = (1,1)
var1,var2 = func()

Эта структура в настоящее время не дает var1, var2 и вызывает исключение.Мне нужно, чтобы он выдавал и вызывал исключение внутри самой этой функции, чтобы другие модули могли напрямую использовать эту функцию без дополнительного кода.Если заявление о доходности не является хорошей идеей, тогда что?

пробовал - [_ for _ in func()], но значение var1 и var2 не меняется так, как ожидается от доходности.пробовал - var1, var2 = next(func()) это дает, но не вызывает исключение.

Ответы [ 2 ]

0 голосов
/ 13 декабря 2018

Хорошо, поэтому сначала нужно решить пару вопросов.
1. Распаковка не работает с отдельными значениями, она пытается исчерпать итерируемое и распаковать все сразу.

def func():
#    ..do something...
    yield 1, 2
    yield 3
    yield 4

a, b = func() #ValueError: too many values to unpack (expected 2)
a, b, c, d = func() #ValueError: not enough values to unpack (expected 4, got 3)
a, b, c = func() #Works
print(a) # (1,2)

2.Доходность останавливает выполнение везде, где встречается.

def func():
    yield 1, 2
    raise Exception

func_gen = func()
print(func_gen) #<generator object func at 0x000000ACB5A5EBF8>
val1, val2 = next(func_gen) #assigns values
next(func_gen) #raises exception only on next pass

3. Должен быть достигнут компромисс (это должно ответить на ваш вопрос)

func_gen = func()
print(func_gen) #<generator object func at 0x000000ACB5A5EBF8>
for _ in func_gen:
    res = _
#raises Exception but res = (1, 2)

4. Вместо этого предлагается (неиспользуйте исключения, это действительно работа для условий if)

def func():
  var1 = 0
  var2 = 1
  flag = not var1 > var2
  yield var1, var2, flag #just add a flag during yield
  #instead of your exception
#  if not var1 > var2:
#    raise Exception(var1,var2)  
  #stuff
  yield 'something else'
func_gen = func()
print(func_gen) #<generator object func at 0x000000ACB5A5EBF8>
for _ in func_gen:
    res = _
    *values, flag = res
    if flag:
        break
var1,var2 = values #0, 1
И последнее, но не менее важное: убедитесь, что вам действительно нужен выход, в том виде, в каком он есть, я подозреваю, что функция сложна для чтения и, возможно, заслуживает разбиения на более мелкие модули.Я настоятельно рекомендую еще раз взглянуть на код и, если возможно, рассмотреть возможность его дальнейшего расширения
0 голосов
/ 13 декабря 2018

Вам нужно выполнить итерацию для выполнения исключения.Следующий минимальный код действительно вызывает исключение.

def func(a,b):
    #..do something...
    yield a, b
    if a!=b:
        raise Exception(a,b)

[_ for _ in func(1,2)]

Это связано с Нет вывода 'print' при использовании yield?

В частности, цитата из одного ответа там "Calling a generator function as in testFunc(1) simply creates a generator instance; it does not run the body of the code."

РЕДАКТИРОВАТЬ Следующее иллюстрирует решение.Это также из приведенной выше цепочки.

def func(a,b):
  #..do something...
  for i in range(10):
    a+=1
    yield a, b
    if a>3:
      raise Exception(a,b)

gen=func(1,2)
next(gen) # returns (2,2)
next(gen) # returns (3,2)
next(gen) # return (4,2)
next(gen) # returns Exception. As expected 

Если вы сделаете next(func()), как вы упомянули в своем редактировании, новый генератор создается каждый раз, когда вы вызываете next(func()).Вместо этого, как показано выше, сначала создайте его экземпляр, а затем позвоните несколько раз.

Сообщество Wiki как связанный вопрос и не может добавить это в комментарии.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...