Python3: subclassing int

Lying awake at night, existential questions cross your mind. What is my purpose? Is there a god? Can you subclass a Python3 int? Only the last one has an answer. You can indeed subclass an int, but there are a few subtleties.

In short, in Python3 depending on whether the built in type is immutable or mutable, you have to do things slightly differently. For the impatient, here is how you subclass an immutable type like an int or str

class Yint(int):
    def __new__(cls, value, payload):
        x = int.__new__(cls, value)
        x.payload = payload
        return x

# This applies for float and str, but not bool

# bool is derived from int, but can't be subclassed itself
class Ybool(int):
    def __new__(cls, value, payload):
        x = int.__new__(cls, bool(value))
        x.payload = payload
        return x

subclassing a mutable type like a list or dict is much more traditional.

class Ylist(list):
    def __init__(self, value, payload):
        list.__init__(self, value)
        self.payload = payload

While I got good hints from here and here the official Python documentation is pretty helpful if you persist. The Basic Customization section has the detail we need, specifically the sections on __new__ and __init__. I will not copy them here, they are short and explain everything you need to know.

Web searches on this topic bring up very little, perhaps because it’s done less often. Why did I have to do this? It all started because I was looking to get the line numbers for elements in a dictionary parsed from a YAML document.

I ran into ruamel.yaml which was great, except that it’s overhead was pretty high for the documents I needed to parse. I also needed to parse the documents in “user real time” which means a user is typing something and I want to parse what they type as they do it. ruamel.yaml was taking way to long (almost a second) to parse these documents, while bare PyYaml was taking 100ms. For my purposes I was able to lightly shim PyYaml to store the line and column numbers (which PyYaml actually keeps track of) in the data as it was being parsed. I wanted to subclass the leaf elements (which are ints, floats and strs and so on) to store this metadata info.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.