1

I wrote a subclass of str like this:

class URL(str):
    def __init__(self, url):
        u = normalize_url(url)
        print u
        super(URL, self).__init__(string=u)

normalize_url() function is used for doing something like url encoding. Everything is ok, until I use json.dumps(). Here is my test code:

>>> u = URL('https://example.com/path contains space.html')
https://example.com/path%20contains%20space.html
>>> json.dumps(u)
'"https://example.com/path contains space.html"'

Why json.dumps() didn't give 'https://example.com/path%20contains%20space.html'

1 Answer 1

1

str (like other immutable objects) does it's initialization in __new__

Construction of an object in python roughly looks like this:

inst = cls.__new__(cls, *args, **kwargs)
cls.__init__(inst, *args, **kwargs)

In your example, you call __init__, but it is too late, the object has already been set up in __new__

You can however fix this!:

class URL(str):
    __slots__ = ()

    def __new__(cls, val):
         val = val.replace(' ', '%20')
         return super(URL, cls).__new__(cls, val)

Now it works!

>>> x = URL('foo bar')
>>> x
'foo%20bar'
>>> json.dumps(x)
'"foo%20bar"'

Note that I've added __slots__ = () to restore the immutability that str had.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.