Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

default() method in Python

I am making an Encoder for converting python objects to json and when researching I see a lot of solutions that include a default method. I'm not an expert in Python, but definitely not a novice either, and I'm wondering if I somehow missed that there is a default method that gets run automatically when a class is called. Or, is this just because I have inherited from the JSONEcoder class (which has a default method, and I am now just overriding)? Can someone clarify? And if so, is it basically the same as the

__init__()

method?

By the way, my encoder looks like this if you need more of a visual:

class ComplexEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, my_custom_object):
            return str(obj)
        return json.JSONEncoder.default(self, obj)
like image 937
AmericanMade Avatar asked Jul 13 '16 21:07

AmericanMade


2 Answers

JSONEncoder has a default method which gets called if it doesn't know how to coerce a particular object into valid JSON. The default implementation just raises TypeError (because it doesn't know how to coerce the type). However, when you override the default method, you have a chance to return an object that the encoder does know how to handle. If you don't know how to handle the type that is input (e.g. it isn't an instance of my_custom_type), then you should either raise TypeError yourself, or call the default method on JSONencoder so that it can raise the error.

Frequently, you'll see super used here for cooperative inheritance:

class ComplexEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, my_custom_object):
            return str(obj)
        return super(ComplexEncoder, self).default(obj)

If all the encoder classes you build are of this form, you can mix them together:

class MySuperEncoder(ComplexEncoder, WidgetEncoder, FooEncoder):
    pass

Now ComplexEncoder will handle the things it knows about (e.g. my_custom_object), WidgetEncoder will encode the things that it knows how to handle (probably Widget instances), and so forth.

like image 60
mgilson Avatar answered Oct 02 '22 23:10

mgilson


Runnning dir(JSONEncoder) gives us:

['__class__',
 '__delattr__',
 '__dict__',
 '__doc__',
 '__format__',
 '__getattribute__',
 '__hash__',
 '__init__',
 '__module__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 '__weakref__',
 'default',  # We found our method, let's see what it does
 'encode',
 'item_separator',
 'iterencode',
 'key_separator']

Running help(JSONEncoder.default) gives us:

default(self, o) unbound json.encoder.JSONEncoder method
    Implement this method in a subclass such that it returns
    a serializable object for ``o``, or calls the base implementation
    (to raise a ``TypeError``).

    For example, to support arbitrary iterators, you could
    implement default like this::

        def default(self, o):
            try:
                iterable = iter(o)
            except TypeError:
                pass
            else:
                return list(iterable)
            # Let the base class default method raise the TypeError
            return JSONEncoder.default(self, o)

So it would seem it's designed this way for you to write your own should you subclass this object.

like image 24
kylieCatt Avatar answered Oct 02 '22 23:10

kylieCatt