Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

python dictionary .get() method with default value throws exception even when it should not even be executed

I am having a dictionary that I would like to retrieve some values from using .get() method and if the key is not present, a default function should be executed that returns the correct value but it should only be executed if the key is not present.

I tried removing the default value and it works, so why does the function gets executed even if it won't be used?

The SQL query will return nothing because it only contains values not already in the dict

def get_port():

    def default():
        cursor.execute("SELECT port FROM table WHERE server=%s LIMIT 1",(server_name,))
        return cursor.fetchone()[0]

    port = {
        'server1': 2222,
        'server2': 2223,
        'server3': 2224
        }
    #print(port.get(server_name)) << Works
    return port.get(server_name, default())

Error:

return cursor.fetchone()[0] TypeError: 'NoneType' object is not subscriptable

I expect the default function to only execute if key is not present..

like image 433
ma7555 Avatar asked Mar 03 '23 17:03

ma7555


1 Answers

the issue with get with a default value which needs build/evaluation is that the code is executed, even if not needed, which can slow down the code, or in your case trigger unnecessary errors.

An alternative could be:

port.get(server_name) or default()

If get returns None because a key is not found, then or default() is activated. But if get returns something, it short-circuits and default() is not called.

(this could fail if get returned empty string, zero, any "falsy" value but in your case - a server name - I'll suppose that it cannot happen)

Another option (maybe overkill here) would be to use a collections.defaultdict object

port = collections.defaultdict(default)
port.update({
        'server1': 2222,
        'server2': 2223,
        'server3': 2224
        })

Then each call to port[server] with an unknown key calls the default function and stores the result in the dictionary. Make port global or persistent and you have a created nice cache: next time the same value is fetched the default is already in the dictionary.

like image 88
Jean-François Fabre Avatar answered Apr 28 '23 04:04

Jean-François Fabre