Python - 生成器案例,没有任何回报

wha*_*sta 9 python for-loop generator

我有一个这样的发电机:

def iterate_my_objects_if_something(self):
    for x in self.my_objects:
        if x.something:
            yield x
Run Code Online (Sandbox Code Playgroud)

我称之为:

for x in self.iterate_my_objects_if_something():
    pass
Run Code Online (Sandbox Code Playgroud)

在没有任何东西要返回的情况下,这会尝试迭代NoneType并抛出异常.

如何返回空发电机?

Wol*_*lph 8

只需做一个简单的检查:

def iterate_my_objects_if_something(self):
    if self.my_objects:
        for x in self.my_objects:
            if x.something:
                yield x
Run Code Online (Sandbox Code Playgroud)


Tad*_*eck 5

重要的是要知道哪个迭代导致了错误。这肯定是在回溯中指出的,但在这种情况下回溯是不必要的(继续阅读)。

生成器的迭代是一个问题吗?

看完之后,这是显而易见的,但值得澄清的是:

  • 空生成器不是 of NoneType,因此迭代它不会导致此类问题:

    >>> def test_generator():
        for i in []:
            yield i
    
    
    >>> list(test_generator())  # proof it is empty
    []
    >>> for x in test_generator():
        pass
    
    >>> 
    
    Run Code Online (Sandbox Code Playgroud)
  • 生成器在定义期间被 Python 识别(我正在简化),并且尝试混合生成器和简单函数(例如,通过使用条件,如下所示)将出现语法错误:

    >>> def test_generator_2(sth):
        if sth:
            for i in []:
                yield i
        else:
            return []
    
    SyntaxError: 'return' with argument inside generator (<pyshell#73>, line 6)
    
    Run Code Online (Sandbox Code Playgroud)

生成器内部的迭代有问题吗?

根据以上结论,错误不在于迭代器的迭代,而在于创建迭代器时发生的情况(生成器中的代码):

def iterate_my_objects_if_something(self):
    for x in self.my_objects:  # <-- only iteration inside generator
        if x.something:
            yield x
Run Code Online (Sandbox Code Playgroud)

所以在某些情况下看似self.my_objects变得None

解决方案

要解决该问题:

  • 保证self.my_objects始终是可迭代的(例如空列表[]),或者
  • 在迭代之前检查它:

    def iterate_my_objects_if_something(self):
        # checks, if value is None, otherwise assumes iterable:
        if self.my_objects is not None:
            for x in self.my_objects:
                if x.something:
                    yield x
    
    Run Code Online (Sandbox Code Playgroud)