J'ai une instance 'graph_main' d'une classe BipartiteGraph que j'ai définie. Tout ce dont j'ai besoin maintenant est de garder cette instance intacte mais de créer une autre instance 'graph1' de cette classe qui est identique à 'graph_main'. Mais pour une raison quelconque, graph_main continue de changer, même si je ne travaille pas du tout. Je suis nouveau à Python, comme deux semaines de neuf. Donc, s'il y a une documentation pertinente que vous pouvez me diriger vers pour apprendre la portée des objets en Python, je vais l'appréprendre.Python: Créer une copie d'une instance d'une classe
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
Je fournis mon dossier Utils au cas où quelqu'un veut courir et voir mais je doute fortement que serait nécessaire. Je m'attends donc à une sortie de nombre constant de nœuds Bit et Check dans graph_main (c'est une classe de graphes bipartite) pour chaque simulation puisque je ne la change pas. Ici, je suppose graph1 = graph_main crée un nouvel objet identique à l'existant graph_main. Est-ce correct et mon erreur est ailleurs?
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 ** # créer un nouvel objet identique à graph_main? ** 'crée en fait une seconde référence à l'objet auquel' graph_main' fait référence. Ces deux variables pointent maintenant vers le même objet. Vous voudrez faire une méthode '.copy()' ou similaire pour vous permettre de cloner votre objet si vous avez besoin d'une instance séparée. –
Ceci est donc similaire aux pointeurs en C++ où vous affectez le pointeur référençant graph_main à graph1 plutôt que de créer une nouvelle variable comme dans MATLAB .. – mathamateur
Sort-of-but-not-quite. Voir http://robertheaton.com/2014/02/09/pythons-pass-by-object-reference-as-explained-by-philip-k-dick/ pour une explication des différences. En règle générale, chaque opération d'assignation en Python crée une nouvelle référence nommée (le nom de la variable à la recherche d'une chose du côté gauche de l'équation) vers un objet (la chose à droite). Même si 'foo' est déjà défini, dire' foo = bar' remplace l'ancienne * référence * par une nouvelle référence avec le même nom. –