使用generator \ iterator的奇怪行为

时间:2016-01-04 19:20:02

标签: python iterator generator

我遇到了一个迭代器的问题,我为一些OOP练习创建了它。

这是有问题的发电机:

'<tr><td>' . ($row2['test']? 'yes' : 'no') . '</td></tr>'

shape.sortedByArea(listOfShapes)是一个静态方法,它需要一个参数,一个列表,它按计算区域排序,然后返回给调用者。 这种方法在这个主要功能中非常有效:

foreach( $result as $row2 )
{ 
    echo '<table ><tr><td>' . $row2['name'] . '</td></tr>' 
        . '<tr><td>' . ($row2['test']? 'yes' : 'no') . '</td></tr>' 
        . '<tr><td>' . $row2['comments'] 
        . '</td></tr>  </table><p>'; 
}

但是当我移动这部分时:

def shapeIterator(listOfShapes):
    print("Generator...")
    print(listOfShapes)
    listOfShapessoretedbyArea = shape.sortedByArea(listOfShapes)
    for shapes in listOfShapessoretedbyArea:
        yield str(shapes)

在主要结尾处,像这样:

if __name__ == '__main__':
    rect = rectangle(20, 5)
    squa = square(2)
    tri = equiTria(2, 5)
    circ = circle(2)
    pent = pentagon(5)
    hexa = hexagon(3)
    listOfShapes = [rect, squa, hexa, tri, circ, pent]
    listOfShapessoretedbyArea = sorted(listOfShapes, key=lambda x: x.calculate_area())
    listOfShapessoretedbyPeri = sorted(listOfShapes, key=lambda x: x.calculate_perimeter())
    listOfShapessoretedbyArea2 = shape.sortedByArea(listOfShapes)
    listOfShapessoretedbyPeri2 = shape.sortedByPerim(listOfShapes)
    iterator = shapeIterator(listOfShapes)
    for i in range(6):
        sleep(1)
        value = next(iterator)
        print(value)
    print("NOT SORTED")
    for shape in listOfShapes:
        print(str(shape))
    print("\nSORTED BY AREA")
    for shape in listOfShapessoretedbyArea:
        print(str(shape))
    print("\nSORTED BY PERIMETER")
    for shape in listOfShapessoretedbyPeri:
        print(str(shape))
    print("\nSORTED BY AREA v2")
    for shape in listOfShapessoretedbyArea2:
        print(str(shape))
    print("\nSORTED BY PERIMETER v2")
    for shape in listOfShapessoretedbyPeri2:
        print(str(shape))

我收到了这个错误:

iterator = shapeIterator(listOfShapes)
for i in range(6):
    sleep(1)
    value = next(iterator)
    print(value)

这很奇怪。尝试做一些天真的调试,我在第二种情况下打印了函数sortedByArea()传递的参数,并且我有效地得到了两个参数。一个是每个语句的最后一个打印的字符串值,第二个是列表本身。

对于每个语句,最后一个字符串值都会引用它:

if __name__ == '__main__':
    rect = rectangle(20, 5)
    squa = square(2)
    tri = equiTria(2, 5)
    circ = circle(2)
    pent = pentagon(5)
    hexa = hexagon(3)
    listOfShapes = [rect, squa, hexa, tri, circ, pent]
    listOfShapessoretedbyArea = sorted(listOfShapes, key=lambda x: x.calculate_area())
    listOfShapessoretedbyPeri = sorted(listOfShapes, key=lambda x: x.calculate_perimeter())
    listOfShapessoretedbyArea2 = shape.sortedByArea(listOfShapes)
    listOfShapessoretedbyPeri2 = shape.sortedByPerim(listOfShapes)
    print("NOT SORTED")
    for shape in listOfShapes:
        print(str(shape))
    print("\nSORTED BY AREA")
    for shape in listOfShapessoretedbyArea:
        print(str(shape))
    print("\nSORTED BY PERIMETER")
    for shape in listOfShapessoretedbyPeri:
        print(str(shape))
    print("\nSORTED BY AREA v2")
    for shape in listOfShapessoretedbyArea2:
        print(str(shape))
    print("\nSORTED BY PERIMETER v2")
    for shape in listOfShapessoretedbyPeri2:
        print(str(shape))
    iterator = shapeIterator(listOfShapes)
    for i in range(6):
        sleep(1)
        value = next(iterator)
        print(value)

我还尝试更改列表的值,并有效地将值&#34;连接&#34;传递给shapeIterator函数的参数是打印的最后一个字符串。

如果需要,这里是主.py中使用的类和导入:

TypeError: sortedByArea() takes 1 positional argument but 2 were given

2 个答案:

答案 0 :(得分:2)

在你的循环中重新绑定 for shape in listOfShapessoretedbyPeri2: print(str(shape)) ,所以它不再是类,而是一个实例。

例如,就在您使用发电机的上方:

__main__

ashape部分中的变量仍然是全局变量,因此替换了生成器使用的类。

您的选择是:

  1. 为循环变量使用不同的名称;例如Shape
  2. 为班级使用其他名称。 Python样式指南建议将CamelCase用于类名,因此将其重命名为if __name__ == '__main__':在这里可以很好地进行。
  3. sortedByArea块下的所有代码放在函数中,以便像循环目标这样的变量名成为 locals
  4. 就个人而言,我实现了2 3;避免污染你的全局命名空间总是一个好主意,所以遵循几乎普遍采用的Python风格指南;这有助于避免将来出现这种错误。

    此外,如果@staticmethod是静态方法,请至少使用class Shape: # ... @staticmethod def sortedByArea(shapes): return sorted(shapes, key=lambda x: x.calculate_area()) @staticmethod def sortedByPerim(shapes): return sorted(shapes, key=lambda x: x.calculate_perimeter()) 装饰器。这样,它甚至可以在实例上用作静态方法:

     var Transform = require('stream').Transform;
     var inherits = require('util').inherits;
    
     function JSONTransform() {
       Transform.call(this);
       this._bufffer = '';
     }
     inherits(JSONTransform, Transform);
     JSONTransform.prototype._transform = function(chunk, enc, cb) {
       this._buffer += chunk;
       cb();
     });
     JSONTransform.prototype._flush = function(cb) {
       try {
         var result = JSON.parse(this._buffer);
         this._buffer = null;
    
         // Do whatever transformations
         // ...
    
         this.push(JSON.stringify(result));
         cb();
       } catch (ex) {
         cb(ex);
       }
     });
    
     // Then just pipe
     request.get('FIRST_URL')
            .pipe(new JSONTransform())
            .pipe(request.post('SECOND_URL'));
    

答案 1 :(得分:1)

您重复使用shape变量,一次用于shape类,一次用于所有for shape in循环中的循环变量。