0

I've got a one type of object, data_entry, that has a 2-dimensional array of other objects, time_entry.

Initialization of time_entries the array within data_entry looks like this:

[([time_entry()] * 12) for i in range(5)]

and initialization of the data_entry looks like this:

thing = data_entry()

Now, I have a list of "things", each which contains it's own 2d array of time_entrys.

Each time_entry has a list as one of it's attributes, initialized like so:

attributes = []

I modify attributes by extending it using .extend().

However, the problem I run into when I do this is EVERY single time_entry object in EVERY single data_entry object gets extended.

I know problems like this can arise from improper initialization of objects, so I'm wondering if perhaps my object creations are poor or there is another python quirk I am unaware of.

ct_inc
  • 23
  • 5

2 Answers2

2

If you are performing the initialization on the class, it will affect all instances of the class. If that’s the case, this is not a result of it being in a list, but of it being on the class. For example:

#!/usr/bin/python

class BedrockDenizen():
    attributes = []


wilma = BedrockDenizen()
fred = BedrockDenizen()

wilma.attributes.extend(['thin', 'smart'])
fred.attributes.extend(['fat', 'stupid'])

print 'Wilma:', wilma.attributes
print 'Fred:', fred.attributes

You will see that both Fred and Wilma are thin, smart, fat, and stupid.

Wilma: ['thin', 'smart', 'fat', 'stupid']

Fred: ['thin', 'smart', 'fat', 'stupid']

One way to fix this is to put the attribute creation into the init method, so that the attribute is per-instance:

class BedrockDenizen():
    def __init__(self):
        self.attributes = []

With that change, only Wilma is thin and smart, and only Fred is fat and stupid.

Wilma: ['thin', 'smart']

Fred: ['fat', 'stupid']

You may also need to show us more code. @Bakuriu notes that the problem may be that you are only creating one instance, and he may be right. For example, if this is closer to your code:

class BedrockDenizen():
    def __init__(self):
        self.attributes = []

neighborhood = [([BedrockDenizen()] * 2) for i in range(2)]

flintstones, rubbles = neighborhood
fred, wilma = flintstones

wilma.attributes.extend(['thin', 'smart'])
fred.attributes.extend(['fat', 'stupid'])

print 'Wilma:', wilma.attributes
print 'Fred:', fred.attributes

Then Fred and Wilma will continue to have the same attributes, because they aren’t really separate people. You may wish to use code more like this:

class BedrockDenizen():
    def __init__(self):
        self.attributes = []

neighborhood = [[BedrockDenizen() for n in range(2)] for i in range(2)]

flintstones, rubbles = neighborhood
fred, wilma = flintstones

wilma.attributes.extend(['thin', 'smart'])
fred.attributes.extend(['fat', 'stupid'])

print 'Wilma:', wilma.attributes
print 'Fred:', fred.attributes

That depends on what your needs are, though, as it seems like an odd way of doing things without more info.

Jerry Stratton
  • 3,287
  • 1
  • 22
  • 30
  • 2
    This is a **different, unrelated** issue. I don't see any `[object] * number` in this code which is what is causing OP's problems. – Bakuriu Jul 05 '16 at 16:24
  • @JerryStratton: No, `[object] * n` creates a list of `n` entries, all of which are the same object. It doesn't make new objects. – user2357112 Jul 05 '16 at 16:27
  • Yea I think this might be right. Give it a try OP – pretzlstyle Jul 05 '16 at 16:27
  • Yes, I was misreading your comment, @Bakuriu. But I still think that the OP’s problem occurs with the “extend”. I could be wrong, though. I’ve added a new option to the answer. – Jerry Stratton Jul 05 '16 at 16:29
  • 1
    This seems to have been the problem - attributes was was initialized within the class rather than in the constructor. Thanks! – ct_inc Jul 05 '16 at 16:50
1

This sounds like your attributes all point to the same list object inside. Then you call extend on the same object every time and modify it.

This is a common issue and discussed at https://docs.python.org/3/faq/programming.html#how-do-i-create-a-multidimensional-list and Python list append behavior

Community
  • 1
  • 1
Robin Roth
  • 1,289
  • 10
  • 13