在 for 循环中循环 comparing/mutating class 个实例会导致意外行为
Looping over and comparing/mutating class instances in a for loop results in unexpected behavior
我有一个 class 节点,它表示有向图上的一个节点。一个节点包含一个序列(一串字母,在这种情况下是 DNA 的 4 个碱基),以及一个前缀和一个由值 k 定义的后缀,其中前缀是前 k 个字母,后缀是最后 k 个字母顺序。
如果一个节点的后缀与另一个节点的前缀相同,则第一个节点应指向第二个节点,并且一个节点可以指向多个其他节点,但不能指向自己。
我正在从一个文件中按顺序读取,从中创建一个节点列表,并尝试设置列表 "nextNodes",每个节点上的 属性 包含所有它指向的节点。
使用两个嵌套的 for-in 循环遍历节点列表,将每个节点与每个节点进行比较,结果是每个节点的 "nextNodes" 列表包含不应指向的节点。此外,每个节点的列表都是相同的。
我尝试使用 itertools.combinations 方法比较节点,认为问题与 for-in 循环和多重比较有某种关系,但无论哪种方式都会发生相同的行为。我很确定问题发生在 for 循环的执行过程中,但我不知道它是什么...??
这是我的代码 (Python 2.7):
import itertools
class Node():
def __init__(self, name, seq='', k=3, nextNodes=[]):
self.name = name
self.seq = seq
self.k = k
self.nextNodes = nextNodes
if len(seq) > k:
self.prefix = seq[:k]
self.suffix = seq[-k:]
else:
self.prefix = 'PREFIX'
self.suffix = 'SUFFIX'
# ...
def getSeq(self):
return self.seq
def setSeq(self, seq):
self.seq = seq
if len(seq) > self.k:
self.prefix = seq[:self.k]
self.suffix = seq[-self.k:]
def getNextNodes(self):
return self.nextNodes
def setNextNode(self, node):
self.nextNodes.append(node)
def getPrefix(self):
return self.prefix
def getSuffix(self):
return self.suffix
def __str__(self):
return self.name
nodes = []
curNode = None
with open('seqs.txt', 'r') as file:
for line in file:
if line[0] == '>':
nodes.append(Node(line[1:].strip('\n')))
curNode = nodes[-1]
else:
curNode.setSeq(curNode.getSeq() + line.strip('\n'))
# When either this for loop or the commented one runs, nextNodes is the
# same for every Node, and contains Nodes that should not be pointed to
for node in nodes:
for otherNode in nodes:
if node.getSeq() != otherNode.getSeq() \
and node.getSuffix() == otherNode.getPrefix():
node.setNextNode(otherNode)
"""
for node1, node2 in itertools.combinations(nodes, 2):
if node1.getSeq() != node2.getSeq():
if node1.getSuffix() == node2.getPrefix():
node1.setNextNode(node2)
if node2.getSuffix() == node1.getPrefix():
node2.setNextNode(node1)
"""
for node in nodes:
for nextNode in node.getNextNodes():
print node, '->', nextNode
示例:
如果 'seqs.txt' 是:
>Node 1
AAACCCGGG
>Node 2
GGGTTTCCC
>Node 3
CCCGGGAAA
我们希望节点 1 指向节点 2,节点 2 指向节点 3,节点 3 指向节点 1。但这是输出:
Node 1 -> Node 2
Node 1 -> Node 1
Node 1 -> Node 3
Node 2 -> Node 2
Node 2 -> Node 1
Node 2 -> Node 3
Node 3 -> Node 2
Node 3 -> Node 1
Node 3 -> Node 3
我认为这里的问题是在 Node.js 的构造函数中使用列表作为 nextNodes 的默认值。列表是可变的,因此当您将默认值分配给 self.nextNodes 时,您实际上是在为每个节点分配相同的列表,而不是新列表。然后,当您在任何节点中附加到它时,它们都会得到它,因为它们指向完全相同的列表。实际上,您附加到 self.nextNodes 实际上是在更改默认值。
我有一个 class 节点,它表示有向图上的一个节点。一个节点包含一个序列(一串字母,在这种情况下是 DNA 的 4 个碱基),以及一个前缀和一个由值 k 定义的后缀,其中前缀是前 k 个字母,后缀是最后 k 个字母顺序。
如果一个节点的后缀与另一个节点的前缀相同,则第一个节点应指向第二个节点,并且一个节点可以指向多个其他节点,但不能指向自己。
我正在从一个文件中按顺序读取,从中创建一个节点列表,并尝试设置列表 "nextNodes",每个节点上的 属性 包含所有它指向的节点。
使用两个嵌套的 for-in 循环遍历节点列表,将每个节点与每个节点进行比较,结果是每个节点的 "nextNodes" 列表包含不应指向的节点。此外,每个节点的列表都是相同的。
我尝试使用 itertools.combinations 方法比较节点,认为问题与 for-in 循环和多重比较有某种关系,但无论哪种方式都会发生相同的行为。我很确定问题发生在 for 循环的执行过程中,但我不知道它是什么...??
这是我的代码 (Python 2.7):
import itertools
class Node():
def __init__(self, name, seq='', k=3, nextNodes=[]):
self.name = name
self.seq = seq
self.k = k
self.nextNodes = nextNodes
if len(seq) > k:
self.prefix = seq[:k]
self.suffix = seq[-k:]
else:
self.prefix = 'PREFIX'
self.suffix = 'SUFFIX'
# ...
def getSeq(self):
return self.seq
def setSeq(self, seq):
self.seq = seq
if len(seq) > self.k:
self.prefix = seq[:self.k]
self.suffix = seq[-self.k:]
def getNextNodes(self):
return self.nextNodes
def setNextNode(self, node):
self.nextNodes.append(node)
def getPrefix(self):
return self.prefix
def getSuffix(self):
return self.suffix
def __str__(self):
return self.name
nodes = []
curNode = None
with open('seqs.txt', 'r') as file:
for line in file:
if line[0] == '>':
nodes.append(Node(line[1:].strip('\n')))
curNode = nodes[-1]
else:
curNode.setSeq(curNode.getSeq() + line.strip('\n'))
# When either this for loop or the commented one runs, nextNodes is the
# same for every Node, and contains Nodes that should not be pointed to
for node in nodes:
for otherNode in nodes:
if node.getSeq() != otherNode.getSeq() \
and node.getSuffix() == otherNode.getPrefix():
node.setNextNode(otherNode)
"""
for node1, node2 in itertools.combinations(nodes, 2):
if node1.getSeq() != node2.getSeq():
if node1.getSuffix() == node2.getPrefix():
node1.setNextNode(node2)
if node2.getSuffix() == node1.getPrefix():
node2.setNextNode(node1)
"""
for node in nodes:
for nextNode in node.getNextNodes():
print node, '->', nextNode
示例: 如果 'seqs.txt' 是:
>Node 1
AAACCCGGG
>Node 2
GGGTTTCCC
>Node 3
CCCGGGAAA
我们希望节点 1 指向节点 2,节点 2 指向节点 3,节点 3 指向节点 1。但这是输出:
Node 1 -> Node 2
Node 1 -> Node 1
Node 1 -> Node 3
Node 2 -> Node 2
Node 2 -> Node 1
Node 2 -> Node 3
Node 3 -> Node 2
Node 3 -> Node 1
Node 3 -> Node 3
我认为这里的问题是在 Node.js 的构造函数中使用列表作为 nextNodes 的默认值。列表是可变的,因此当您将默认值分配给 self.nextNodes 时,您实际上是在为每个节点分配相同的列表,而不是新列表。然后,当您在任何节点中附加到它时,它们都会得到它,因为它们指向完全相同的列表。实际上,您附加到 self.nextNodes 实际上是在更改默认值。