I would like to add some information actually about UserString
class.
Python's built-in types, like str
, are actually not real Python classes, but C constructions (assuming the standard Python implementation, CPython). It helps with speed and probably with Python-C interoperability, but the behaviour of built-ins can be different from usual user's classes. There are cases when this implementation detail matters.
This is an example of such situation. Probably, regexp engine behind re
is written in C and works with C strings. UserString
"simulates a string object" but it is not one.
It seems that all C routines do not work with UserString
. For example, you cannot run importlib
, subprocess
, or os.path
on this class.
There was an enhancement proposition about it in 2001. But a fix was not implemented, because there is no easy way to do it.
Therefore, there is no standard way to fix it. You need to use some work-around: either .data
as in chepner's answer, or as in the linked question do str(UserString('foo'))
.
In addition, the error message
TypeError: expected string or bytes-like object
actually means that it needs a str
object. By default "string" means str
in Python. Which can be confusing in case of "string-like" objects etc.
Finally, in my real use case I had to use a string-like class MyString
which could be extended with new methods in future.
For the time being I just used a MyString = str
and thought that it will be easily extensible in the future when the need comes.
The need came, I defined class MyString(UserString)
and my tests told me that they need a string.
Now, in somewhat awkward and non-Pythonic way, half of my code treats MyString
as a string and another half does MyString('foo').data
. And to make things worse this MyString
class is a part of the interface of one of the modules.
So a user must know the implementation details behind the interface of the module...
In my case it seems that I can code around this issue.
But that requires some re-writing of the whole module.
So probably the feature implemented with UserString
is not worth the effort right now.