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: Different objects of the same class references the same dictionary
Type: Stage: resolved
Components: Interpreter Core Versions: Python 3.7
process
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: Nosy List: Kevin Young, ammar2, steven.daprano
Priority: normal Keywords:

Created on 2020-02-05 06:35 by Kevin Young, last changed 2022-04-11 14:59 by admin. This issue is now closed.

Messages (4)
msg361407 - (view) Author: Kevin Young (Kevin Young) Date: 2020-02-05 06:35
Test code:

class Test(object):
    def __init__(self, a={}):
        self._a = a
    
    def put(self, k, v):
        self._a[k] = v

if __name__ == '__main__':
    t1 = Test()
    t1.put('aa', '11')
    t1.put('bb', '22')
    
    t2 = Test()
    t2.put('cc', '33')
    for k, v in t2._a.items():
        print(k, '=', v)

Output:
aa = 11
bb = 22
cc = 33

The expected output should be:
cc = 33

My workaround:
self._a = dict(a)

I have tested on both Python 3.7.3 and 3.8.1, they share the same results.
I'm not sure if this is a bug or on-purpose feature of python. Could someone provide some guidance for me? Thank you.
msg361408 - (view) Author: Ammar Askar (ammar2) * (Python committer) Date: 2020-02-05 06:55
This is a common mistake, you'll find the FAQ entry for it here: https://docs.python.org/3/faq/programming.html#why-are-default-values-shared-between-objects

It's not necessarily a "feature" but default values in functions are only created once, when the function is defined. Subsequent calls will refer to that same initially created object.
msg361409 - (view) Author: Kevin Young (Kevin Young) Date: 2020-02-05 07:16
Thank you, Ammar!
I thought the default values were locally scoped under the __init__() function.
msg361451 - (view) Author: Steven D'Aprano (steven.daprano) * (Python committer) Date: 2020-02-05 20:41
Ammar: it is definitely a feature that default values are created only once, when the function is created, not over and over again every time the function is called. (These are sometimes called "early binding" and "late binding" respectively.)

With early binding, you know what the default value is: it is the object at the time the function was created.

(But note that *mutable* objects may be mutated from one call to the next: they are not "reset" to their initial value each time. This is occasionally useful, to implement static storage across function calls, but also often a Gotcha that trips people up.)

With late binding, a default value like this:

    def function(value=a+b+c):

could change from one call to the next, if the values a, b or c change.

Both early and late binding have advantages and disadvantages, but if a language only has one, it is better to have early binding (as Python has) and let the coder do the late binding inside the function:

    def function(value=None):
        if value is None:
            value = a+b+c
History
Date User Action Args
2022-04-11 14:59:26adminsetgithub: 83737
2020-02-05 20:41:36steven.dapranosetnosy: + steven.daprano
messages: + msg361451
2020-02-05 07:16:06Kevin Youngsetmessages: + msg361409
2020-02-05 06:55:56ammar2setstatus: open -> closed

nosy: + ammar2
messages: + msg361408

resolution: not a bug
stage: resolved
2020-02-05 06:35:54Kevin Youngcreate