4

In Perl I can do something like this:

foo = a // b;

What I'm wondering is if Python has anything similar to this. I've tried the following, but obviously it does not work:

foo = {'key1':'val1','key2':'val2'}
bar = foo['doesntexist'] or foo['key1']

And I get the error:

KeyError: 'doesntexist'
Franz Kafka
  • 780
  • 2
  • 13
  • 34

2 Answers2

2

The reason your method is not working is because Python raises an error before your boolean expression is able to be evaluated. Instead of simply indexing the dictionary, you need to use .get() instead. Rather than raising an error, .get() returns None which allows your expression to be evaluated correctly:

bar = foo.get('doesntexist') or foo.get('key1')

Note that if the value of the first key is 0 or any other value that evaluates to false, your method will fail. If this is fine with you than use the method above.

However, if you'd like not to have the behavior described above, you must test if the first value is None. At this point however, it would be better to simply extract this logic to a separate function:

def get_key(d, test_key, default_key):
    """
    Given a dictionary(d), return the value of test_key.
    If test_key does not exists, return the default_key 
    instead.
    """
    if d.get(test_key) is not None:
        return d.get(test_key)
    return d.get(default_key)

Which can be used like so:

foo = {'key1':'val1','key2':'val2'}
bar = get_key(foo, 'doesntexist', 'key1')
Christian Dean
  • 22,138
  • 7
  • 54
  • 87
2

You don't need the or at all:

bar = foo.get('doesntexist', foo['key1'])
Francisco
  • 10,918
  • 6
  • 34
  • 45
  • Perfect, thank you! That is exactly what I was looking for. – Franz Kafka Mar 04 '17 at 01:11
  • This answers a slightly different question than was asked - `get` doesn't help in the `foo = a // b` case, it specifically only helps in the `foo = a[x] if x in a else a[y]` case. – Ken Williams Jun 17 '22 at 17:54
  • The other problem is that `foo['key1']` must be evaluated whether it's necessary or not. This doesn't handle the `foo = cached // compute()` case that `//` is so useful for. So I'd say the correct answer to the question is really "No, python doesn't have an equivalent operator, you need to build one yourself." – Ken Williams Jun 17 '22 at 17:57