default() method in Python
Asked Answered
U

3

5

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)
Under answered 13/7, 2016 at 21:10 Comment(0)
T
6

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.

Tableland answered 13/7, 2016 at 21:18 Comment(0)
T
2

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.

Tradein answered 13/7, 2016 at 21:18 Comment(0)
T
1

I think this method is defined in json.JSONEncoder as described here. default(o) should return a serializable version of the given object or pass it to its superclass.

Textualist answered 13/7, 2016 at 21:19 Comment(1)
Yeah, that's what I kind of started thinking, too. Just wasn't sure about if default() was some sort of magic method that I didn't know about. Thanks!Under

© 2022 - 2024 — McMap. All rights reserved.