2
\$\begingroup\$

I need a constant (dictionary with values and default return value if there are no defined value for a key). Searching for any ways to simplify the code.

Without a default value I can simply define a dictionary like this:

REDUCE_VALUE = {
    "honda": 0.95,
    "suzuki": 0.85,
    "yamaha": 0.87
}

But with a default value it looks not so good:

from collections import defaultdict
REDUCE_VALUE = defaultdict(lambda: "0.9")
REDUCE_VALUE["honda"] = 0.95
REDUCE_VALUE["suzuki"] = 0.85
REDUCE_VALUE["yamaha"] = 0.87
\$\endgroup\$
  • \$\begingroup\$ Are you aware that there can't be two different "suzuki" entries in the dictionary? I'm not sure that this code does what you intend. \$\endgroup\$ – mkrieger1 Oct 24 '16 at 10:05
  • 1
    \$\begingroup\$ The get method of the standard dictionary returns a default value when the given key is missing. \$\endgroup\$ – mkrieger1 Oct 24 '16 at 10:10
  • \$\begingroup\$ Yes, there is an error with double "suzuki". The last one can be "bmw" for example. An second one default value must be in integer, not string. Thanks. I suppose it's a bad idea to edit my question after publication. \$\endgroup\$ – misterioss Oct 24 '16 at 11:14
  • \$\begingroup\$ @misterioss Yes, it's a bad idea to remove or replace the part which has already been answered or commented. However, I suppose you can safely extend a question by adding a new part to it. Or, even better, make another, corrected question and add a follow-up note. \$\endgroup\$ – CiaPan Oct 24 '16 at 13:20
4
\$\begingroup\$

The same way that you would with dict. From the documentation for collections.defaultdict it says:

The first argument provides the initial value for the default_factory attribute; it defaults to None. All remaining arguments are treated the same as if they were passed to the dict constructor, including keyword arguments.

This means we can use all, bar b, of: (from the dict docs.)

>>> a = dict(one=1, two=2, three=3)
>>> b = {'one': 1, 'two': 2, 'three': 3}
>>> c = dict(zip(['one', 'two', 'three'], [1, 2, 3]))
>>> d = dict([('two', 2), ('one', 1), ('three', 3)])
>>> e = dict({'three': 3, 'one': 1, 'two': 2})
>>> a == b == c == d == e
True

Since you're overwriting suzuki, I'd remove the first assignment, as dicts are unordered, and so it's up to chance which it uses. And as Alex points out, you should keep the value data type consistent.

REDUCE_VALUE = defaultdict(lambda: 0.9, {"honda": 0.95, "suzuki": 0.87})
\$\endgroup\$
  • \$\begingroup\$ @Graipher Gotta love it when that happens, :) Feel free to answer anyway, quality over FGITW. \$\endgroup\$ – Peilonrayz Oct 24 '16 at 10:11
  • \$\begingroup\$ Nah, yours has nicer quotes from the docs. I wrote up what @mkrieger suggested, though. \$\endgroup\$ – Graipher Oct 24 '16 at 10:17
3
\$\begingroup\$

You can use update method of dictionary to make it pretty

from collections import defaultdict
REDUCE_VALUE = defaultdict(lambda: "0.9")
REDUCE_VALUE.update({
"honda": 0.95,
"suzuki": 0.85,
"suzuki": 0.87
})

Also please note that in you defaultdict definition you are using string as value, while other values are floats, not sure which one you need. So fix it yourself.

\$\endgroup\$
1
\$\begingroup\$

As @mkrieger1 commented, you could use dict.get.

From the python docs:

get(key[, default])

Return the value for key if key is in the dictionary, else default. If default is not given, it defaults to None, so that this method never raises a KeyError.

REDUCE_VALUE = {
    "honda": 0.95,
    "suzuki": 0.85,
}

>>> REDUCE_VALUE.get('suzuki', 0.95)
0.85

>> REDUCE_VALUE.get('yamaha', 0.95)
0.95

Normally, you would probably define the default value as a constant, instead of having it as a magic number as I did here.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.