0

These codes seem the same on paper but their outcomes show they are different codes under the hood. Is it because of scope within the loop? The output shows on the first example any alteration of the first dictionary changes the second dictionary as well. The second example allows for individual dictionary contents alteration without changing the other dictionary which is also of the same name at creation.

new_person = {'haircolor':'blonde'}
new_person = {'haircolor':'blonde'}

people = [new_person,new_person]

people[0]['haircolor'] = 'brunette'

print(people)

#######################################

people = []

for num in range(2):
    new_person = {'haircolor':'blonde'}
    people.append(new_person)

people[0]['haircolor'] = 'brunette'

print(people)
Aplet123
  • 33,825
  • 1
  • 29
  • 55
  • [{'haircolor': 'brunette'}, {'haircolor': 'brunette'}] [{'haircolor': 'brunette'}, {'haircolor': 'blonde'}] – needyPheonix Dec 30 '20 at 21:41
  • tl;dr in your first example they all point to the same dictionary so a change across one changes them all. – Aplet123 Dec 30 '20 at 21:43
  • You're reusing the `new_person` identifier in the first example. The two `new_person`s in `people = [new_person,new_person]` are the same `new_person`. – ChrisGPT was on strike Dec 30 '20 at 21:45
  • yes that is what I have come to accept. However, where I am confused is why in the second example they arent pointing to each other. Would not they also be pointing to the same dictionary since every time the loop runs it creates a dictionary with the same name as well. – needyPheonix Dec 30 '20 at 21:47
  • @Aplet123, that's not a good dupe for this question. – ChrisGPT was on strike Dec 30 '20 at 21:51
  • @Chris Take that up with the people who closed this question as a dupe: https://stackoverflow.com/q/57990256 – Aplet123 Dec 30 '20 at 21:52
  • @Aplet123, that's not the same thing. Here, OP is writing `new_person = {'haircolor':'blonde'}` twice, expecting to have two different dicts. But since the _identifier_ `new_person` is reused they only get one. That's not the same as doing `{} * 3`. – ChrisGPT was on strike Dec 30 '20 at 21:54
  • 1
    @needyPheonix, try doing `new_person = None` followed by `new_person = {'haircolor':'blonde'}` and then take a look at `new_person`. Then flip the first two lines around and try again. When you do `people = [new_person,new_person]` you're using `new_person` two times. That single identifier can't point to two things at the same time. It's always pointing to whatever you assigned it most recently. – ChrisGPT was on strike Dec 30 '20 at 21:57

1 Answers1

3

In the first case, defining new_person = {'haircolor':'blonde'} the second time has no effect at all, it just replaces the first declaration. In the second case, the loop creates two distinct dictionaries, so when changing one, the other stays the way it was.

ChrisGPT was on strike
  • 127,765
  • 105
  • 273
  • 257
MercifulSory
  • 337
  • 1
  • 14
  • "the second time has no effect at all, it just replaces the first declaration"—actually it _does_ have an effect. The second `new_person` overwrites the first. It's the second definition that's in place when OP creates `people`. It would be clearer if the two had different colours of hair. – ChrisGPT was on strike Dec 30 '20 at 21:47
  • I know, I just formulated in a different way. Thanks tho – MercifulSory Dec 30 '20 at 21:48
  • Saying it "has no effect at all" isn't explaining in a different way; it's misleading. If either has "no effect at all" it's the _first_ one. This isn't exactly accurate, but it's closer to the truth. – ChrisGPT was on strike Dec 30 '20 at 21:50
  • I meant that if the second one was omitted, things would've stayed the same in this case. – MercifulSory Dec 30 '20 at 21:52
  • That's also true if the _first_ one is omitted. And it's only true in this case because the same dict literal was used in both cases. If they had been different it would _not_ be the same to omit the second one but it _would_ be the same to omit the first. – ChrisGPT was on strike Dec 30 '20 at 21:52
  • You are totally right – MercifulSory Dec 30 '20 at 21:53
  • okay i get that! this had me so tangled up. So basically in the first example I have list with two references to the same dictionary, correct. – needyPheonix Dec 30 '20 at 21:56
  • @needyPheonix, in the first example you only have _one_ reference to _one_ object. You are reusing the `new_person` identifier. When you assign it the second time, references to the first dict are lost and Python can throw that dict away. `new_person` can only ever point to one thing at a time. If you had used `new_person_1` and `new_person_2` you'd have two separate dicts, each with one reference. It's confusing since you're using the same value both times. Try making one a brunette right out of the gate. – ChrisGPT was on strike Dec 30 '20 at 21:58