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: Mutable instance variables don't get new references with args.
Type: behavior Stage: resolved
Components: Interpreter Core Versions: Python 3.6
process
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: Nosy List: ekarademir, eric.smith, r.david.murray
Priority: normal Keywords:

Created on 2017-11-29 11:15 by ekarademir, last changed 2022-04-11 14:58 by admin. This issue is now closed.

Files
File name Uploaded Description Edit
bug.py ekarademir, 2017-11-29 11:15 Demonstration of the possible bug.
Messages (4)
msg307219 - (view) Author: Ertuğrul Karademir (ekarademir) * Date: 2017-11-29 11:15
Hello,

I've searched all over Google and this bug tracker with all combinations of keywords that I can associate with this issue, but I couldn't find an explanation that makes sense or fits the issue.

I know that when dealing with mutable variables, class variables share the same reference with all instances, so to assign separate attributes for instances, mutable variables should be instance level variables.

However when I create a class like the following,

    class Base:
        def __init__(self, props=list(), foo='foo base'):
            self.props = props
            self.foo = foo
        
        def insert_prop(self, i):
            self.props.append(i)

and run this:

    if __name__ == '__main__':
        base = Base()

        base.insert_prop(1)
        base.insert_prop(2)

        print('base props before base2, 3 creation:', base.props)

        base2 = Base()
        base3 = Base([41, 42])

        print('base props after base2, 3 creation:', base.props)
        print('base2 props after base2, 3 creation:', base2.props)
        print('base3 props after base2, 3 creation:', base3.props)

        base2.insert_prop(51)
        base3.insert_prop(61)

        print('base props after insertion:', base.props)
        print('base2 props after insertion:', base2.props)
        print('base3 props after insertion:', base3.props)

the output is this:

    base props before base2, 3 creation: [1, 2]
    base props after base2, 3 creation: [1, 2]
    base2 props after base2, 3 creation: [1, 2]
    base3 props after base2, 3 creation: [41, 42]
    base props after insertion: [1, 2, 51]
    base2 props after insertion: [1, 2, 51]
    base3 props after insertion: [41, 42, 61]

So initiating base3 with explicit args gives it a new reference to the props variable but base and base2 share the same reference. So suddenly props is hoisted to class level.

I actually encountered this behaviour when trying to do the same thing with child classes with no __init__ method like:

    class Sub1(Base):
        pass

The whole code is attached.

Is this an expected behaviour? If so I couldn't find a gotcha anywhere.

Regards,

Ertugrul
msg307220 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2017-11-29 11:28
This is defined behavior. Try searching for "mutable default parameter". For example, here's an old post on it:

http://www.effbot.org/zone/default-values.htm

This isn't related to class vs. instance attributes, but rather the default parameter 'props' being modified.
msg307221 - (view) Author: Ertuğrul Karademir (ekarademir) * Date: 2017-11-29 11:32
Thank you

Ertuğrul Karademir

On Wed, Nov 29, 2017 at 11:28 AM, Eric V. Smith <report@bugs.python.org>
wrote:

>
> Eric V. Smith <eric@trueblade.com> added the comment:
>
> This is defined behavior. Try searching for "mutable default parameter".
> For example, here's an old post on it:
>
> http://www.effbot.org/zone/default-values.htm
>
> This isn't related to class vs. instance attributes, but rather the
> default parameter 'props' being modified.
>
> ----------
> nosy: +eric.smith
> resolution:  -> not a bug
> stage:  -> resolved
> status: open -> closed
>
> _______________________________________
> Python tracker <report@bugs.python.org>
> <https://bugs.python.org/issue32168>
> _______________________________________
>
msg307456 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2017-12-02 20:51
For the record: https://docs.python.org/3/faq/programming.html#id13
History
Date User Action Args
2022-04-11 14:58:55adminsetgithub: 76349
2017-12-02 20:51:06r.david.murraysetnosy: + r.david.murray
messages: + msg307456
2017-11-29 11:32:25ekarademirsetmessages: + msg307221
2017-11-29 11:28:00eric.smithsetstatus: open -> closed

nosy: + eric.smith
messages: + msg307220

resolution: not a bug
stage: resolved
2017-11-29 11:15:04ekarademircreate