从生成器返回int - Python

时间:2016-10-29 12:48:48

标签: python python-3.x

我一直试图找出一种从生成器中获取int值的方法,但是脚本引擎会向我抛出错误。

def inorderTraversal(self, node):
        if(node.left):
            for n in self.inorderTraversal(node.left):
                yield n[0]
        yield node.data[0]
        if(node.right):
            for n in self.inorderTraversal(node.right):
                yield n[0] 

错误是:

  

文件" ac.py",第142行,inorderTraversal
      yield n [0] TypeError:' int'对象不可订阅

其中

n = {10,"X"}。我试图搜索它,但我知道没有解决方案满足我的需求。

3 个答案:

答案 0 :(得分:2)

您需要将yield n[0]替换为yield n。您已经产生了节点的(整数)值,因此无需进一步索引。

编辑:添加了解释。

答案 1 :(得分:0)

n = {10,"X"}

print(n[0]) 

产量

TypeError: 'set' object does not support indexing

不是确切的错误,但我在Android IDE上测试这个,所以这并不让我感到惊讶。

答案就是你试图下标一组,但这意味着什么?集合是无序的,因此集合中没有“0th”元素。如果要随机访问,则需要切换到列表。

或者,如果您只是寻找一个简单的临时容器,则元组是可索引的。

如果n是节点数据,您可以创建一个Node类,然后直接访问该字段而不是索引。

答案 2 :(得分:0)

如果您的yield node.data[0]是正确的,那么当您在递归情况下执行yield n[0]时,就像您在该分支中执行yield node.data[0][0]一样。因此,将其更改为yield n,因为递归案例已经为您提供了所需的内容,您只需要将其传递给它。

此外,在设计树时,您通常会以.data存储的方式执行此操作,以及树的用户希望存储在其中的数据,并且不必担心这是什么或者它看起来如何,所以你通常做yield node.data

同样在python 3中,您可以使用yield from作为这种for循环的快捷方式。

考虑到这些,您的代码应该如下所示

def inorderTraversal(self, node):
    if node.left:
        yield from self.inorderTraversal(node.left)
    yield node.data
    if node.right:
        yield from self.inorderTraversal(node.right)

因为你没有提供问题的Minimal, Complete, and Verifiable example我只能猜测,所以

让我们看一下这样的示例树代码

class Node:
    def __init__(self, data, left=None, right=None):
        self.data  = data
        self.left  = left
        self.right = right

用它来构建一个类似于wikipedia

中的样本树

sample tree

test1 = Node(6,
             Node(2,
                  Node(1),
                  Node(4,
                       Node(3),
                       Node(5)
                       )
                  ),
             Node(7,
                  None,
                  Node(9,
                       Node(8)
                       )
                  )
             )

让我们再次使用[int,str]

的数据结构
test2 = Node([6,"F"],
            Node([2,"B"],
                 Node([1,"A"]),
                 Node([4,"D"],
                      Node([3,"C"]),
                      Node([5,"E"])
                      )
                 ),
            Node([7,"G"],
                 None,
                 Node([9,"I"],
                      Node([8,"H"])
                      )
                 )
            )

现在有趣的部分,inorder功能,首先是你的

def inorderBad(node):
    if node.left:
        for n in inorderBad(node.left):
            yield n[0]
    yield node.data[0]
    if node.right:
        for n in inorderBad(node.right):
            yield n[0]

让我们使用test2

进行测试
>>> list(inorderBad(test2))
Traceback (most recent call last):
  File "<pyshell#0>", line 1, in <module>
    list(inorderBad(test2))
  File "C:\Users\David\Documents\Python Scripts\stackoverflow_test.py", line 26, in inorderBad
    for n in inorderBad(node.left):
  File "C:\Users\David\Documents\Python Scripts\stackoverflow_test.py", line 27, in inorderBad
    yield n[0]
TypeError: 'int' object is not subscriptable
>>> 
看起来很熟悉?我所说的错误是n[0]的递归情况,当你到达底部节点(在这种情况下为A)它产生数据[0](在这种情况下为1),在上面的节点(B)中得到这个价值,并尝试再次产生它只是这次尝试产生它的第一个值,并在这方面失败,因为错误说

现在让我们解决它

def inorder2(node):
    if node.left:
        for n in inorder2(node.left):
            yield n
    yield node.data[0]
    if node.right:
        for n in inorder2(node.right):
            yield n         

并测试它

>>> list(inorder2(test2))
[1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> 

按预期工作,让我们试试另一个

>>> list(inorder2(test1))
Traceback (most recent call last):
  File "<pyshell#6>", line 1, in <module>
    list(inorder2(test1))
  File "C:\Users\David\Documents\Python Scripts\stackoverflow_test.py", line 35, in inorder2
    for n in inorder2(node.left):
  File "C:\Users\David\Documents\Python Scripts\stackoverflow_test.py", line 35, in inorder2
    for n in inorder2(node.left):
  File "C:\Users\David\Documents\Python Scripts\stackoverflow_test.py", line 37, in inorder2
    yield node.data[0]
TypeError: 'int' object is not subscriptable
>>> 

自然它失败了因为inorder2不够通用,在你当前的实现中也是如此,如果你想要字符串呢?您是否考虑过这一点?一般来说,这些问题不应与此特定功能相关,它应仅提供所有数据 inorder

所以一般的顺序和添加yield from

def inorder(node):
    if node.left:
        yield from inorder(node.left)
    yield node.data
    if node.right:
        yield from inorder(node.right)

测试

>>> list(inorder(test2))
[[1, 'A'], [2, 'B'], [3, 'C'], [4, 'D'], [5, 'E'], [6, 'F'], [7, 'G'], [8, 'H'], [9, 'I']]
>>> list(inorder(test1))
[1, 2, 3, 4, 5, 6, 7, 8, 9]
>>>