---
title: the old and the __new__
slug: the-old-and-the-__new__
date: 2026-09-25 21:33:03 UTC-05:00
tags: python
category: programming
description: >
 In which I remember a programming thing that I
 frequently forget.
type: text
---

I occasionally want to subclass `str` for one reason or another.
A working toy example:

```python
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__`:

```python
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

<!-- TEASER_END -->

  [str]: https://docs.python.org/3/builtins/stdtypes.html#textseq

The issue is that the `str` constructor also takes arguments.
The [`str` documentation][str] 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.
