Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

From Ruby to Python - Is there an equivalent of "try"?

In Ruby (on Rails, actually), I have the try function:

[].try(:[], 1) # => nil
[10].try(:[], 1) # => nil
[10, 20].try(:[], 1) # => 20
[10, 20, 30].try(:[], 1) # => 20

{}.try(:foo) # => nil
{ foo: 'bar' }.try(:foo) # => 'bar'

The function basically is a shortcut to avoid ifs to check if the position is present.
Is there something similar in Python?

like image 569
Igorzovisk Avatar asked Sep 24 '17 12:09

Igorzovisk


2 Answers

Dictionaries: dict.get

You can use dict.get:

d = {'foo' : 'bar'}

print(d.get('foo'))
'bar'

print(d.get('xxxxx'))
None

You can also pass a default parameter to get:

print(d.get('xxxxx', 'Invalid Key!'))
Invalid Key!

The default value is printed out when the key does not exist in the dictionary.


Lists: custom try-except block

Unfortunately, lists do not have a dict.get equivalent in their API, so you'll need to implement one yourself. Thankfully, you can extend the list class and override __getitem__ to do this cleanly.

class MyList(list):
    def __getitem__(self, idx, default='oops'):
        try:
            return super().__getitem__(idx)
        except IndexError:
            return default

l = MyList([10, 20])

l[1]
# 20

l[3]
# 'oops'

      
like image 93
cs95 Avatar answered Sep 28 '22 09:09

cs95


It is not possible to have a method like try in Python, since try crucially relies on monkey patching Object and NilClass, and their Python equivalents (object and NoneType) cannot be monkey patched:

def try_object(self, f, *args, **kwargs):
    return getattr(self, f)(*args, **kwargs)

def try_none(self, f, *args, **kwargs):
    return None

object.try   = try_object
object.try   = try_object
#            ^
# SyntaxError: invalid syntax

NoneType.try = try_none
#            ^
# SyntaxError: invalid syntax

However, you can write a global try function that behaves similar:

def tryy(obj, f, *args, **kwargs):
    if obj is None:
        return None
    else:
        return getattr(obj, f)(*args, **kwargs)

tryy([10, 20], '__getitem__', 1)
# >>> 20

tryy(None, '__getitem__', 1)
# >>> None
like image 31
Jörg W Mittag Avatar answered Sep 28 '22 08:09

Jörg W Mittag