How do I return class type instead of built-in type when inheriting from built-in class – Python

Question:

class StringMethods(str):

    """
    StringMethods class:

    A class inheriting from the built in python 'str' class,
    but with extended methods for string analysis, password checking etc.
    """        

    def contains(self, char: str) -> bool:
        """ True if self contains specified char """
        
        return char in self


    def containsany(self, chars: Iterable) -> bool:
        """ True if self contains any specifed chars """
        
        for char in chars:
            if str(char) in self:
                return True
        return False

    
    def hasdigit(self) -> bool: return self.containsany("0123456789")
    def haslower(self) -> bool: return self.containsany("abcdefghijklmnopqrstuvwxyz")
    def hasupper(self) -> bool: return self.containsany("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
    def haswhitespace(self) -> bool: return self.contains(" ")
    
    
    def removechar(self, char: str) -> "StringMethods":
        """ Remove all instances of specified char from self """
        
        return "".join([i for i in self if i != str(char)])
        
    
    def removechars(self, chars: Iterable) -> "StringMethods":
        """ Remove all specified chars from self """

        chars = [str(char) for char in chars]
        return "".join([i for i in self if str(i) not in chars])
    
    
    def __sub__(self, subtrahend) -> "StringMethods":
        return self[:-subtrahend]
    
    def __add__(self, addend) -> "StringMethods":
        return f"{self}{self[-1]}"


y = StringMethods("hello")
y = y.upper() # it is now 'str' type, not 'StringMethods' type

I have my own extended str class, but I want the user to be able to continually use their initial variable as an instance of my class, yet when they use a string method, it is converted to a string and no longer a StringMethods() object. Anyone know how I can fix this? Thanks

Asked By: darragh

||

Answers:

Rather than inheriting directly from str, you could inherit from collections.UserString.

from collections import UserString


class StringMethods(UserString):

    """
    StringMethods class:

    A class inheriting from the built in python 'str' class,
    but with extended methods for string analysis, password checking etc.
    """
    ...
>>> x = StringMethods("hello")
>>> type(x.upper())
<class '__main__.StringMethods'>

Reading on UserString: https://docs.python.org/3.6/library/collections.html#collections.UserString

Answered By: M69k65y
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.