简体   繁体   中英

Weird thing in python classes ?

I was trying to implement a shortest path algorithm in python. I ran into some trouble when I attempted to connect my points on the path.

I have a class called NODE I made an array of these nodes and then created new nodes in them like this:

nodes = []
for r in range ( 0, 3 ):
    for c in range ( 0, 3 ):
        nodes.append( NODE( c*WIDTH/20 + 30, r*HEIGHT/20 + 30, 10 ) )

This created nodes, which is fine, I can draw them just fine.
At first I attempted connecting them by adding a list of node objects into the the NODE class. I ran into some issues, I thought the problem is with the recursive classes, so to test I did this.
Where connections is a blank array within the NODE class.

nodes[0].connections.append( 0 )
print nodes[0].connections

nodes[1].connections.append( 1 )
print nodes[1].connections
print nodes[0].connections

This is where I found the problem, Maybe I'm just being stupid, or It's a language thing ? Dunno, but I thought I'd ask.

The output is this:
[ 0 ]
[ 0, 1 ]
[ 0, 1 ]

As you can see, I only added 1 object to the connections list in the index 1. However when I print the contents, I see two.... And this confuses me.

Possibilty 1: your code looks like this:

class NODE:
    connections = []
    def __init__(self, value):
        self.value = value

nodes = [NODE(23), NODE(42)]

nodes[0].connections.append( 0 )
print nodes[0].connections
nodes[1].connections.append( 1 )
print nodes[1].connections
print nodes[0].connections

Solution: class instance attributes should be defined inside __init__ . If you define connections at the class level, then every single instance of NODE will share the same one connections list.

class NODE:
    def __init__(self, value):
        self.value = value
        self.connections = []

Possibility 2: your code looks like this:

class NODE:
    def __init__(self, value, connections = []):
        self.value = value
        self.connections = connections

nodes = [NODE(23), NODE(42)]

nodes[0].connections.append( 0 )
print nodes[0].connections
nodes[1].connections.append( 1 )
print nodes[1].connections
print nodes[0].connections

Solution: the default value in an argument list is created only once, so all instances of NODE using that default value will share the same one list. use a non-mutable sentinel value to indicate that no argument was passed. None is usually suitable for this task.

class NODE:
    def __init__(self, value, connections = None):
        self.value = value
        if connections is not None:
            self.connections = connections
        else:
            self.connections = []

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM