the old and the __new__
I occasionally want to subclass str for one reason or another.
A working toy example:
import colorama, enum class ColorData(str): def __new__(cls, name, terminal_setup_code): self = super().__new__(cls,name) self.setup_code = terminal_setup_code self.reset_code = colorama.Style.RESET_ALL return self def print(self, *args, **kwargs): """Print text wrapped in the appropriate color codes.""" file = kwargs.pop('file', None) flush = kwargs.pop('flush', None) print(self.setup_code, end='', file=file) print(*args, **kwargs) print(self.reset_code, end='', file=file, flush=flush) class Color(ColorData, enum.ReprEnum): RED = R = 'red', colorama.Fore.LIGHTRED_EX BLUE = B = 'blue', colorama.Fore.LIGHTBLUE_EX ... if __name__ == "__main__": for color in Color: color.print("This text is", color)
The thing is that I usually want to override __init__ rather than __new__:
class Subclass(str): def __init__(self, value, *args): # wrong! super().__init__(self, value) ... # do stuff with *args
This wrong code fails with the error
TypeError: decoding str is not supported
The issue is that the str constructor also takes arguments.
The str documentation currently gives four calling signatures:
class str(*, encoding='utf-8', errors='strict') class str(object) class str(object, encoding, errors='strict') class str(object, *, errors)
Additional arguments get passed to str.__new__, and the first one
gets interpreted as the encoding. You have to override __new__ to
prevent this.