This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: When creating list of dictionaries and updating datetime objects one by one, all values are set to last one of the list.
Type: behavior Stage: resolved
Components: Interpreter Core Versions: Python 3.5
process
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: Nosy List: Joona Mörsky, gdr@garethrees.org, vaultah
Priority: normal Keywords:

Created on 2017-12-01 11:05 by Joona Mörsky, last changed 2022-04-11 14:58 by admin. This issue is now closed.

Messages (3)
msg307382 - (view) Author: Joona Mörsky (Joona Mörsky) Date: 2017-12-01 11:05
When creating list of dictionaries and updating datetime objects one by one, all values are set to last one of the list.

Ubuntu Linux 4.10.0-40-generic #44~16.04.1-Ubuntu SMP Thu Nov 9 15:37:44 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
Python 3.5.2



>>>import datetime

>>>b = datetime.datetime.utcnow()
>>>b = b.replace(hour=0,minute=0,second=0,microsecond=0,tzinfo=datetime.timezone.utc)

>>>a = [{}] * 3

>>>for inx in range(3):

...    a[inx]['time'] = b + datetime.timedelta(minutes=inx*10)


[{'time': datetime.datetime(2017, 12, 1, 0, 20, tzinfo=datetime.timezone.utc)}, {'time': datetime.datetime(2017, 12, 1, 0, 20, tzinfo=datetime.timezone.utc)}, {'time': datetime.datetime(2017, 12, 1, 0, 20, tzinfo=datetime.timezone.utc)}]

>>>import datetime

>>>b = datetime.datetime.utcnow()
>>>b = b.replace(hour=0,minute=0,second=0,microsecond=0,tzinfo=datetime.timezone.utc)

>>>a = [ ]

>>>for inx in range(3):

...    a.append({"time": b + datetime.timedelta(minutes=inx*10)})

[{'time': datetime.datetime(2017, 12, 1, 0, 0, tzinfo=datetime.timezone.utc)}, {'time': datetime.datetime(2017, 12, 1, 0, 10, tzinfo=datetime.timezone.utc)}, {'time': datetime.datetime(2017, 12, 1, 0, 20, tzinfo=datetime.timezone.utc)}]
msg307383 - (view) Author: Dmitry Kazakov (vaultah) * Date: 2017-12-01 11:59
This is not a bug in Python. Refer to this page for the explanation: https://stackoverflow.com/questions/240178/list-of-lists-changes-reflected-across-sublists-unexpectedly

Basically, [{}]*3 creates a list with three references to the same dictionary.
msg307384 - (view) Author: Gareth Rees (gdr@garethrees.org) * (Python triager) Date: 2017-12-01 12:04
The behaviour of the * operator (and the associated gotcha) is documented under "Common sequence operations" [1]:

    Note that items in the sequence s are not copied; they are referenced
    multiple times. This often haunts new Python programmers ...

There is also an entry in the FAQ [2]:

    replicating a list with * doesn’t create copies, it only creates
    references to the existing objects

[1] https://docs.python.org/3/library/stdtypes.html#sequence-types-list-tuple-range
[2] https://docs.python.org/3/faq/programming.html#faq-multidimensional-list
History
Date User Action Args
2022-04-11 14:58:55adminsetgithub: 76375
2017-12-01 12:04:37gdr@garethrees.orgsetstatus: open -> closed

nosy: + gdr@garethrees.org
messages: + msg307384

resolution: not a bug
stage: resolved
2017-12-01 11:59:33vaultahsetnosy: + vaultah
messages: + msg307383
2017-12-01 11:05:58Joona Mörskycreate