2012-08-05 56 views
0

我创建了类似list()的类,但是可以向它添加字符串,这些字符串将被单词上的空格分割,并且这些单词将被添加到类实例。与减法相同:减法从类实例中删除单词(如果有的话)。鼻子测试+类迭代器=奇怪的行为

我在鼻子测试中遇到了奇怪的行为:当我只是改变声明的顺序时,行为发生了变化。

下面是测试:

from nose.tools import * 

def test_isub_str(self): 
    u = params() 

    u += "1 2 3 4" 
    u -= "2 3" 

    ok_("1" in u, u) 
    ok_("2" not in u, u) 
    ok_("3" not in u, u) 
    ok_("4" in u, u) 

该测试失败,并输出如下:

Traceback (most recent call last): 
    File "tests.py", line 71, in test_isub_str 
    ok_("4" in u, u) 
    assert expr, msg 
AssertionError: 1 4 

怪, “U” 被转储为 “1 4”,而是 “4” 并不在断言测试期间在“u”中找到。当我改变主张的以下列最有趣的情况:

ok_("1" in u, u) 
ok_("4" in u, u) 
ok_("2" not in u, u) 
ok_("3" not in u, u) 

然后测试都通过确定,这是正确的,预期的行为。它看起来像“不在”语句改变了后面的“in”语句的行为。我很惊讶。

最后,这里是我的课:

class params(): 
    def __init__(self): 
     self.index = 0 # iterator index 
     self.values = [] # list of stored values 

    def __iadd__(self, addvalues): 
     if isinstance(addvalues, str): 
      addvalues = addvalues.split(" ") 
     # add all values to this instance if they are list() or params() 
     # and not exist in current instance 
     if isinstance(addvalues, params) or isinstance(addvalues, list): 
      for value in addvalues: 
       if isinstance(value, str) and value not in self.values: 
        self.values.append(value) 
       else: 
        raise TypeError 
      return self 
     else: 
      raise TypeError 

    def __isub__(self, subvalues): 
     if isinstance(subvalues, str): 
      subvalues = subvalues.split(" ") 
     # substract all values from this instance if they are list() or params() 
     # and existing in current instance 
     if isinstance(subvalues, params) or isinstance(subvalues, list): 
      for value in subvalues: 
       if isinstance(value, str) and value in self.values: 
        self.values.remove(value) 
       else: 
        raise TypeError 
      return self 
     else: 
      raise TypeError 

    def __iter__(self): 
     return self 

    def next(self): 
     if self.index >= len(self.values): 
      raise StopIteration 
     else: 
      self.index += 1 
      return self.values[self.index - 1] 

    def __str__(self): 
     return " ".join(self.values) 

所以问题是:为什么这样奇怪的行为发生?我在迭代器功能中遗漏了一些东西?或者这个鼻子测试错误?

回答

0

不,这不是一个错误nosetests,我认为,当你做

ok_("1" in u, u) 

u.index为1,当你这样做:

ok_("2" not in u, u) 
ok_("3" not in u, u) 

u.index是2.当你做

ok_("4" in u, u) 

u.index依然是200,而你的 “下一个” 方法引发StopIteration异常,因为2> = LEN(self.values)。

在你的第二个案例u.index仍然是1,当你做:

ok_("4" in u, u) 
+0

谢谢!这是一个原因!我根据几个不同的例子编写了迭代器方法,如[this](http://stackoverflow.com/questions/19151/build-a-basic-python-iterator),他们都只是简单地返回'self'。在每个__iter __()调用上重新设置索引/迭代器是否好的做法? – stunpix 2012-08-05 17:29:32

+0

我认为在这种情况下,最好删除'next'方法(你实际上在你的迭代器中没有任何状态),并且改变'__iter__'这样的东西:'iter(self.values)'。 – 2012-08-05 17:32:06

+0

再次感谢。我按你的建议做了,'__iter __()'现在很简单。 – stunpix 2012-08-06 08:30:25