pythonpython-3.xdictionary

Is `mydict.get(x, x)` eqivalent to `mydict.get(x) or x`?


When using a dictionary to occasionally replace values, are .get(x, x) and .get(x) or x equivalent?

For example:

def current_brand(brand_name):
    rebrands = {
        "Marathon":    "Snickers",
        "Opal Fruits": "Starburst",
        "Jif":         "Cif",
        "Thomson":     "TUI",
    }
    
    return rebrands.get(brand_name, brand_name)
    # or
    return rebrands.get(brand_name) or brand_name

    # this is forbidden - cannot use `default` keyword argument here
    return rebrands.get(brand_name, default=brand_name)

assert current_brand("Jif") == "Cif"
assert current_brand("Boots") == "Boots"

I think .get(x) or x is clearer, but that's pretty much a matter of opinion, so I'm curious if there's a technical benefit or drawback to one or the other I've not spotted.

Edit: sorry, to be clear, I'm assuming that the dictionary does not contain falsey values as that would't make sense in this context (i.e. in the example above you're not recording that "Somerfield" rebranded as "")


Solution

  • In answer to your original question: or will short-circuit if your value is Falsey, so there are plenty of values where the two statements will behave differently.

    my_dict = {
        'foo': 0,
        'bar': "",
        'baz': [],
    }
    
    x = 'foo'
    print(repr(my_dict.get(x, x)))
    print(repr(my_dict.get(x) or x))
    

    In answer to your edit, if you can guarantee that your dict is definitely a dict, and that the values in your dict are always Truthy, then the two should behave equivalently.

    There may be some performance tradeoffs either way, but I generally don't bother to get hung up on that. If this code ends up in a hot loop, then profile it, write the faster version, then stick a comment nearby explaining that your code's weird because the weird way is faster.

    In my opinion the downside of your method is philosophical. To my eyes, .get(x, ...) communicates your intent as "retrieve key x, and if it's not there, default to ...". .get(x) or ... communicates "if it's not there, or is defined as a Falsey value, default to ...". The intent displayed in your question suggests you should use .get(x, x), but for a simple example like this it hardly matters.