python-产生并引发异常

时间:2018-12-13 15:17:05

标签: python exception-handling generator

我正在尝试编写一个产生两个变量并且还根据条件引发异常的函数。 这是一个最小的示例:

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并引发异常。 我需要它来产生并在此函数本身内引发异常,以便其他模块可以直接使用此函数而无需其他代码。 如果yield语句不是一个好主意,那是什么?

已尝试-[_ for _ in func()],但var1和var2的值没有像产量期望的那样变化。
已尝试-var1, var2 = next(func())会产生但不会引发异常。

2 个答案:

答案 0 :(得分:0)

您需要迭代执行该异常。遵循最少的代码确实会引发异常。

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

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

这与No 'print' output when using 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作为相关问题,因此无法在评论中添加。

答案 1 :(得分:0)

好,所以首先要解决几个问题。
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.Yield会在遇到任何地方停止执行。

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
  1. 最后但并非最不重要的一点是,请确保您确实需要产量,就目前而言,我怀疑该功能既难以阅读,也值得将其拆分成较小的模块。我强烈建议您再看一遍代码,并考虑在可能的情况下进一步分解它。