代码之家  ›  专栏  ›  技术社区  ›  Sharvari Gc

python-yield和raise异常

  •  1
  • Sharvari Gc  · 技术社区  · 6 年前

    我正在尝试编写一个函数,该函数生成两个变量,并根据条件引发异常。 下面是一个简单的例子:

    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 回复  |  直到 6 年前
        1
  •  0
  •   Paritosh Singh    6 年前

    好吧,那么先解决几个问题。
    1。解包对单个值不起作用,它试图用尽iterable并立即解包所有内容。

    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. 最后但并非最不重要的是,确保你真的需要收益率,就目前的情况来看,我怀疑这个函数既难以阅读,也可能值得拆分成更小的模块。我强烈建议您再看一眼代码,如果可能的话,可以考虑进一步破坏它。
        2
  •  0
  •   Dinesh    6 年前

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

    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()) 正如您在编辑中提到的,每次调用时都会创建新的生成器 下一个(函数()) . 相反,如上所示,先实例化它,然后调用多次。

    社区wiki作为相关问题,无法在评论中添加此内容。