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: dict.setdefault (setdefault of dictionary)
Type: enhancement Stage: resolved
Components: Versions: Python 3.8
process
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: Nosy List: da-dada, eric.smith, remi.lapeyre
Priority: normal Keywords:

Created on 2019-12-08 18:47 by da-dada, last changed 2022-04-11 14:59 by admin. This issue is now closed.

Messages (6)
msg358016 - (view) Author: (da-dada) Date: 2019-12-08 18:47
from the docu I expected at the second call just a return of value and not a second calculation: there is room for improvement, as Elon Musk would say..

class Ddefault:

    def __init__(self):
        vars(self).setdefault('default', self.set_default())
        vars(self).setdefault('default', self.set_default())

    def set_default(self):
        print(vars(self))
        return 'default'

if __name__ == "__main__":
    Ddefault()
msg358019 - (view) Author: Rémi Lapeyre (remi.lapeyre) * Date: 2019-12-08 18:55
>
>
>     def __init__(self):
>         vars(self).setdefault('default', self.set_default())
>         vars(self).setdefault('default', self.set_default())
>

This code is equivalent to

    def __init__(self):
        x = self.set_default()
        vars(self).setdefault('default', x)

        x = self.set_default()
        vars(self).setdefault('default', x)

>
because the argument is evaluated before the call to setdefault() so you
can't optimise anything here.
msg358021 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2019-12-08 19:39
Right. If you want the value only calculated once, then just call it once.

You might be interested in collections.defaultdict, which takes a factory function, and only calls it as needed.
msg358036 - (view) Author: (da-dada) Date: 2019-12-08 21:47
I have no problem of making my programme run properly (asking first if in dict etc), but I just read the docu of dict.setdefault

setdefault(key[, default]) 
If key is in the dictionary, return its value. If not, insert key with a value of default and return default. default defaults to None.

and it clearly reads if the key is.. return its value, with a full stop;
so either the docu is wrong (but proposes exactly the needed shortcut) or python is as it is: come in & find out
msg358037 - (view) Author: Rémi Lapeyre (remi.lapeyre) * Date: 2019-12-08 22:39
The documentation is correct, in Python argument are computed before the
call to a function, not when they are used. You can try other functions
than dict.setdefault() and see that the behaviour is always the same.

Le dim. 8 déc. 2019 à 22:47, da-dada <report@bugs.python.org> a écrit :

>
> da-dada <georg.klingenberg@travedsl.de> added the comment:
>
> I have no problem of making my programme run properly (asking first if in
> dict etc), but I just read the docu of dict.setdefault
>
> setdefault(key[, default])
> If key is in the dictionary, return its value. If not, insert key with a
> value of default and return default. default defaults to None.
>
> and it clearly reads if the key is.. return its value, with a full stop;
> so either the docu is wrong (but proposes exactly the needed shortcut) or
> python is as it is: come in & find out
>
> ----------
>
> _______________________________________
> Python tracker <report@bugs.python.org>
> <https://bugs.python.org/issue38998>
> _______________________________________
>
msg358043 - (view) Author: (da-dada) Date: 2019-12-09 00:45
my use case is different (I do a loop), but what I expected from the docs (just for fun!)

class Ddefault:

    def __init__(self):
        vars(self).setdefault('default', self.set_default() if not 'default' in vars(self) else self.default)
        vars(self).setdefault('default', self.set_default() if not 'default' in vars(self) else self.default)
        print(vars(self))

    def set_default(self):
        print(vars(self))
        return 'default'

if __name__ == "__main__":
    Ddefault()

may be the coding diverted from the docs after the fixing of issue 13521 and no one dares correcting..
anyway, I will probably keep my old coding (performance, if there is any)
History
Date User Action Args
2022-04-11 14:59:24adminsetgithub: 83179
2019-12-09 00:45:34da-dadasetmessages: + msg358043
2019-12-08 22:39:03remi.lapeyresetmessages: + msg358037
2019-12-08 21:47:05da-dadasetmessages: + msg358036
2019-12-08 19:39:29eric.smithsetstatus: open -> closed

nosy: + eric.smith
messages: + msg358021

resolution: not a bug
stage: resolved
2019-12-08 18:55:43remi.lapeyresetnosy: + remi.lapeyre
messages: + msg358019
2019-12-08 18:47:22da-dadacreate