0

Is there any way to add functionality to dict itself? There are a log of reasons I would like to do this - but for instance - I'd like to do something like:

def safe_get( the_dictionary, key ):
    return None if the_dictionary is None else the_dictionary.get(key)

# this does NOT work, because dict is a built in type
dict.safe_get = safe_get

Because this is tolerable:

result = event.safe_get("request_context").safe_get("identity").safe_get("sourceIp")

And this is ridiculous:

result = safe_get( safe_get( safe_get( event, 'request_context'), 'identity'), 'sourceIp')

Or is there another (shorter == better) way of doing the same thing?

When I google I see people defining their own classes and things - but I don't create "event" - it comes from amazon, so I have no control over it, and can't change it to another type. I could wrap it - but that would be even more code :(

krmogi
  • 2,588
  • 1
  • 10
  • 26
Darren Oakey
  • 2,894
  • 3
  • 29
  • 55
  • This similar question does not seem to apply here. The OP wants to essentially create a "NoneOrDict" class, because he must call `safe_get` method on None as well. Although you do not create event, you can cast it to your custom class. E.g., you can create a `SafeDict` class, which initializes with a dict or None as an input. Hold it as the instance property. Define `safe_get` method on it. Then, you should be able to `MyDict(event).safe_get("request_context").safe_get("identity").safe_get("sourceIp")` – Kota Mori Nov 17 '21 at 12:09

1 Answers1

0

You can't just add an attribute to built-in dict objects, however:

from types import MethodType


class MyDict(dict):
    pass


def safe_get(self, key):
    return None if key is None else self.get(key)


d = {'a': 1}
md = MyDict(d)

# this wouldn't work:
# d.safe_get = MethodType(safe_get, d)
# but this does:
md.safe_get = MethodType(safe_get, d)
print(md.safe_get('a'))
print(md.safe_get('b'))

Result:

1
None

Of course, you could just add the method to the class:

class MyDict(dict):
    def safe_get(self, key):
        return None if key is None else self.get(key)

d = {'a': 1}
md = MyDict(d)
print(md.safe_get('a'))
print(md.safe_get('b'))

Or even override the standard behaviour:

class MyDict(dict):
    def __getitem__(self, key):
        return None if key not in self else self.get(key)


d = {'a': 1}
md = MyDict(d)
print(md['a'])
print(md['b'])

By the way, you wrote return None if the_dictionary is None else the_dictionary.get(key) but I assume you meant something more along the lines of return None if key not in the_dictionary else the_dictionary.get(key)?

Of course, you could update the solution I presented similarly. Only my final suggestion makes this assumption currently.

Grismar
  • 27,561
  • 4
  • 31
  • 54