Can I add custom methods/attributes to built-in Python types?

Solution 1:

You can't directly add the method to the original type. However, you can subclass the type then substitute it in the built-in/global namespace, which achieves most of the effect desired. Unfortunately, objects created by literal syntax will continue to be of the vanilla type and won't have your new methods/attributes.

Here's what it looks like

# Built-in namespace
import __builtin__

# Extended subclass
class mystr(str):
    def first_last(self):
        if self:
            return self[0] + self[-1]
        else:
            return ''

# Substitute the original str with the subclass on the built-in namespace    
__builtin__.str = mystr

print str(1234).first_last()
print str(0).first_last()
print str('').first_last()
print '0'.first_last()

output = """
14
00

Traceback (most recent call last):
  File "strp.py", line 16, in <module>
    print '0'.first_last()
AttributeError: 'str' object has no attribute 'first_last'
"""

Solution 2:

Just tried the forbbidenfruit!

here is the code, very simple!

from forbiddenfruit import curse


def list_size(self):
    return len(self)

def string_hello(self):
    print("Hello, {}".format(self))

if __name__ == "__main__":
    curse(list, "size", list_size)
    a = [1, 2, 3]
    print(a.size())
    curse(str, "hello", string_hello)
    "Jesse".hello()

Solution 3:

Yes indeed, but you have to define a new class of the same type and it should inherit from that type.

For example:

class list(list):
    def __init__(self, *args):
        super().__init__(args)
    def map(self, function):
        return [function(i) for i in self]

a = list(1, 2, 3, 4, 5)

def double(i):
    return i * 2

print(a.map(double))

Solution 4:

NOTE: this QA is marked as duplicate to this one, but IMO it asks for something different. I cannot answer there, so I am answering here.


Specifically, I wanted to inherit from str and add custom attributes. Existing answers (especially the ones saying you can't) didn't quite solve it, but this worked for me:

class TaggedString(str):
    """
    A ``str`` with a ``.tags`` set and ``.kwtags`` dict of tags.
    Usage example::
      ts = TaggedString("hello world!", "greeting", "cliche",
                        what_am_i="h4cker")
      (ts.upper(), ts.tags, ts.kwtags)
    """

    def __new__(cls, *args, **kwargs):
        return super().__new__(cls, args[0])

    def __init__(self, s, *tags, **kwtags):
        super().__init__()
        self.tags = set(tags)
        self.kwtags = kwtags

Hopefully this helps someone! Cheers,
Andres