Append of lists in Python

2019-06-14 12:09发布

问题:

A strange append of list in python.

Here I defined a class

class test:
    group = []
    def __init__(self,name):
    self.name = str(name)

Then I write those

test0 = test(0)
test1 = test(1)
test_list = [test0, test1]

I want to save test1.name into test0.group

test_list[0].group.append(test_list[1].name)

I print test0.group , it's ['1'] , everything is OK. But while I want to save test0.name into test1.group

test_list[1].group.append(test_list[0].name)

Then I print test1.group , it's ['1','0']. I don't know why it isn't ['0']? By the way, here I print test0.group , it's also the ['1','0'].

回答1:

That is because the group variable is a variable shared by all instances of the class test and therefore test0 and test1 share the same group. When you do the first append i.e. '1' it is fine but when you do the second append you are appending to the same list and therefore it becomes ['1', '0']. In fact, if you print test0.group as the last line of your code, you will see that it also is ['1', '0'] because they are the same variable. I am not sure what you are trying to achieve but if you want separate groups then you should make them self.group instead and move them into the __init__ method. If you can rephrase your question, I can maybe help you with what you are actually trying to achieve.



回答2:

I believe the issue is in the class definition:

class test:
    group = []
    def __init__(self,name):
    self.name = str(name)

At this point, the __init__ method does nothing and self.name = str(name) never gets called. You need to indent self.name = str(name) in order for it to be in __init__'s body. Try this:

class test:
    group = []
    def __init__(self,name):
        self.name = str(name)


回答3:

This is basically the same problem discussed in here.

Surprisingly? when you define class, Python interpreter execute class field. And then if you create a new instance of the class, class field is not executed. So class field is executed once only when you define class. Like:

class someClass:
    someVar = 0        #<---This class field is executed once
    def __init__(self):
        pass

OK. Now you defined class. Next you create new instance of the class. Like:

instance1 = someClass()
instance2 = someClass()

This will create new memory and copy data from someClass. Now instance1 and instance2 do not share memory space. They have own independent memory space. So instance1.someVar and instance2.someVar has different memory space. But 0 in instance1.someVar and 0 in instance2.someVar are completely same object(0 is on same memory space). You can ensure it doing like:

print id(instance1.someVar)==id(instance2.someVar)

So you can find 0 is completely same object.

This is not the only case when someClass.someVar = 0. Same thing will happen when you use [] replacement of 0.


Back to your code. You can simply occur your problem doing like this:

class test:
    group = []
    def __init__(self,name):
        self.name = str(name)

test0 = test(0)
test1 = test(1)

test0.group.append(100)

print test0.group
print test1.group
#[100]
#[100]
#will be printed

This is because test0.group and test1.group point same object. Like:

+-----------+
|test0.group|------+
+-----------+      |
                   v
               +-------+
               |  []   |
               +-------+
                   ^
+-----------+      |
|test1.group|------+
+-----------+

When you executed test0.group.append(100), it becomes like:

+-----------+
|test0.group|------+
+-----------+      |
                   v
               +-------+
               | [100] |
               +-------+
                   ^
+-----------+      |
|test1.group|------+
+-----------+

Also you can set another object. Like:

test1.group = "123"

Then test1.group becomes like:

+-----------+
|test0.group|------+
+-----------+      |
                   v
               +-------+
               | [100] |
               +-------+

+-----------+       +-----+
|test1.group|------>|"123"|
+-----------+       +-----+

Sorry for my bad English. I hope it helps. :)