我有一個我已經定義的BipartiteGraph類的實例'graph_main'。我現在需要的只是保持這個實例不變,但創建另一個與'graph_main'相同的類的實例'graph1'。但由於某種原因,graph_main也會不斷變化,而我根本就沒有使用它。我是Python的新手,像幾個星期的新手。因此,如果有相關的文檔可以指向我,以瞭解Python中對象的範圍,那麼我會提供它。Python:創建一個類的實例的副本
MWE:
import numpy
import testBipartiteUtils
import random
#These are Bipartite graph parameters
N=30 #No of Bit Nodes
K=10 #No of Check Nodes
rdeg=2
graph_main = testBipartiteUtils.BipartGraph([])
for NodeIndex in range(0, K):
graph_main.addBitNode(NodeIndex)#Adding Bit Node. No edges added
for NodeIndex in range(0, N):
graph_main.addChkNode(NodeIndex)#Adding Check Node. No edges added
attachments=random.sample(range(0,K),rdeg)
for j in attachments:
graph_main.addEdge([j,NodeIndex])
for z in range(0,10):
chan=[]
for i in range(0,N):
chan.append(0)
graph1=graph_main **#creating a new object identical to graph_main?**
PeelGraph=testBipartiteUtils.Peeling(graph1,chan)
PeelGraph.zeroStep()
print "graph_main Nodes are-",len(graph_main.BitNodes),len(graph_main.ChkNodes)
print "graph1 Nodes are-",len(graph1.BitNodes),len(graph1.ChkNodes)
del PeelGraph
print "z=",z
我提供我的utils的文件,以防有人想運行它,看看,但我很懷疑這將是必要的。所以我期待在graph_main(這是一個二部圖類)中爲每個模擬輸出恆定數量的比特和檢查節點,因爲我沒有改變它。這裏我假設graph1 = graph_main創建一個與現有graph_main相同的新對象。這是否正確,我的錯誤在別處?
testBipartiteUtils.py
import numpy
class Edge:
def __init__(self, n1, n2):
"""Constructor. Takes bit and check node IDs as arguments"""
self.node1=n1
self.node2=n2
def getNodes(self):
"""Returns a list containing the bit and check nodes for this edge"""
return [self.node1, self.node2]
def hasNodes(self, n1, n2):
"""Takes two node IDs. Returns true if the IDs match the two nodes of this edge in that order."""
if(self.node1==n1 and self.node2==n2):
return True
return False
class BitNode:
""" Basic node class."""
def __init__(self, name):
"""Constructor. Takes a node ID"""
self.ID=name
self.neighbors=[]
self.degree= 0
def addNeighbors(self, nbs):
"""Adds a list of neighbors to the current list. Takes a list of node IDs"""
for i in range(0, len(nbs)):
if(not nbs[i] in self.neighbors):
self.neighbors.append(nbs[i])
self.degree+=1
def getID(self):
"""Returns node ID"""
return self.ID
def getNeighbors(self):
"""Returns list of neighbor IDs"""
return self.neighbors
class ChkNode:
def __init__(self, name):
"""Constructor. Takes a node ID"""
self.ID=name
self.neighbors=[]
self.chan = int(-1)
self.degree= 0
def addNeighbors(self, nbs):
"""Adds a list of neighbors to the current list. Takes a list of node IDs"""
for i in range(0, len(nbs)):
if(not nbs[i] in self.neighbors):
self.neighbors.append(nbs[i])
self.degree+=1
def getID(self):
"""Returns node ID"""
return self.ID
def getNeighbors(self):
"""Returns list of neighbor IDs"""
return self.neighbors
class BipartGraph:
def __init__(self, eds):
"""Constructor. Takes a list of edge primitives, which is a list of two node IDs.
Iterates through the edges, creates nodes for unique node IDs, and adds all edges and nodes.
"""
self.size = 0
self.BitNodes = []
self.ChkNodes = []
self.edges = []
for i in range(0, len(eds)):
self.addEdge(eds[i])
def containsEdge(self, edgep):
"""Checks for an edge in the graph. Takes an edge primitive, which is a list of two node IDs. First ID is bit node, second ID is of Check node"""
for e in self.edges:
if(e.hasNodes(edgep[0], edgep[1])):
return True
def getBitNode(self, name):
"""Checks if a given Bit Node ID exists in the graph. If not, it creates and adds a Bit Node for the given ID. Returns the Bit Node"""
for i in range(0, len(self.BitNodes)):
if(self.BitNodes[i].getID()==name):
return self.BitNodes[i]
newNode = BitNode(name)
self.BitNodes.append(newNode)
return self.BitNodes[len(self.BitNodes)-1]
def getChkNode(self, name):
"""Checks if a given Chk Node ID exists in the graph. If not, it creates and adds a Chk Node for the given ID. Returns the Chk Node"""
for i in range(0, len(self.ChkNodes)):
if(self.ChkNodes[i].getID()==name):
return self.ChkNodes[i]
newNode = ChkNode(name)
self.ChkNodes.append(newNode)
return self.ChkNodes[len(self.ChkNodes)-1]
def getEdges(self):
"""Returns list of edges"""
return self.edges
def addBitNode(self, name):
"""Adds a Bit node, based on Bit node ID"""
newNode = BitNode(name)
self.BitNodes.append(newNode)
def addChkNode(self, name):
"""Adds a Check node, based on node ID"""
newNode = ChkNode(name)
self.ChkNodes.append(newNode)
def addEdge(self, edgep):
"""Adds an edge into the graph, and updates neighbors & degrees of relevant nodes.
Takes an edge primitive, a list of two node IDs
"""
if(not self.containsEdge(edgep)):
no1 = self.getBitNode(edgep[0])
no2 = self.getChkNode(edgep[1])
newEdge = Edge(edgep[0], edgep[1])
self.edges.append(newEdge)
no1.addNeighbors([no2.getID()])
no2.addNeighbors([no1.getID()])
class Peeling:
"""peeling decoder on a Bipartite graph class.
"""
def __init__(self, G,chan):
"""Constructor. Takes a graph and channel output vector as arguments"""
self.graph=G
for i in range(0,len(self.graph.ChkNodes)):
self.graph.ChkNodes[i].chan=chan[i]
self.deg1Chks=[]
def zeroStep(self):
self.graph.BitNodes.pop(0)
def peelIter(self):
self.graph.ChkNodes.pop(0)
'graph1 = graph_main **#創建一個與graph_main相同的新對象**實際上是創建對graph_main引用的對象的第二個引用。現在這兩個變量都指向了完全相同的對象。你需要創建一個'.copy()'方法或類似的方法來允許你克隆你的對象,如果你需要一個單獨的實例。 –
所以這與C++中的指針類似,你將指向graph_main的指針指定給graph1,而不是像MATLAB中那樣創建一個新變量.. – mathamateur
Sort-of-but-not-quite。有關差異的解釋,請參閱http://robertheaton.com/2014/02/09/pythons-pass-by-object-reference-as-explained-by-philip-k-dick/。作爲一個經驗法則,Python中的每個賦值操作都會爲一個對象(右側的對象)創建一個新的命名引用(變量名稱在等式左邊)。即使已經定義了'foo',說'foo = bar'用一個新的引用替換了舊的*引用*並且具有相同的名字。 –