2016-02-19 83 views
1

我有一個我已經定義的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) 
+1

'graph1 = graph_main **#創建一個與graph_main相同的新對象**實際上是創建對graph_main引用的對象的第二個引用。現在這兩個變量都指向了完全相同的對象。你需要創建一個'.copy()'方法或類似的方法來允許你克隆你的對象,如果你需要一個單獨的實例。 –

+0

所以這與C++中的指針類似,你將指向graph_main的指針指定給graph1,而不是像MATLAB中那樣創建一個新變量.. – mathamateur

+0

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'用一個新的引用替換了舊的*引用*並且具有相同的名字。 –

回答

1

使用deepcopy函數來創建一個新的指針的相同實例(而不是淺拷貝,這是另一個變量指向同一個對象)。

import copy 

graph1= copy.deepcopy(graph_main) 
+0

謝謝。那完美的作品。但是我的問題比Kirk-need指出的要深刻得多,因爲我需要理解任務的不同和新的命名參考, – mathamateur

-1

我不知道這個,但不能你只是做到這一點?...

x = ClassName(arguments, arguments...) 

dup_of_x = x 

因此,X專賣店x和dup_of_x還存儲X