У меня есть класс StringPlus, представляющий строку с дополнительными данными. Я хотел бы сделать его совместимым с .join(), который используется внутри библиотеки, в которую я загружаю список StringPlus. Я не могу контролировать звонок join(). Простое определение __str__() не работает:
class StringPlus:
def __init__(self, string: str, extra_data):
self._string = string
self._extra_data = extra_data
def __str__(self):
return self._string
a = StringPlus("a", [1, 2, 3])
b = "".join([a, "b"])
assert b == "ab"
Любые подсказки?
Str.join необходимо передать итерацию строк, поэтому это невозможно сделать без преобразования каждого элемента в list.
"".join(map(str, [a, "b"]))
# or
"".join(str(x) for x in [a, "b"])
Однако изменение определения класса на подкласс str может позволить этому работать без ручного преобразования.
class StringPlus(str):
Не вариант, так как у меня нет доступа к библиотеке, которая joins.
@NicoSchlömer Тогда вы можете попробовать создать подкласс str.
Это, наверное, решение. Я помню, что у меня были проблемы с этим, хотя. Позвольте мне поиграть с ним снова.
Наследовать str:
>>> class StringPlus(str):
... def __init__(self, string=''):
... self._extra_data = [1, 2, 3]
...
>>> "".join([StringPlus("a"), "b"])
'ab'
Если вам нужно настроить параметры построения, вам также необходимо перегрузить метод __new__ (обратите внимание, что параметры в методах __new__ и __init__ должны быть согласованы):
>>> class StringPlus(str):
... def __new__(cls, string, extra_data):
... return super().__new__(cls, string)
... def __init__(self, string, extra_data):
... self._extra_data = extra_data
...
>>> "".join([StringPlus("a", [1, 2, 3]), "b"])
'ab'
Или просто определите метод __new__:
>>> class StringPlus(str):
... def __new__(cls, string, extra_data):
... self = super().__new__(cls, string)
... self._extra_data = extra_data
... return self
...
Вы можете снабдить свой пользовательский класс StringPlus методом join, чтобы он вел себя как/похоже str.join:
class StringPlus:
def __init__(self, string: str):
self._string = string
self._extra_data = [1, 2, 3]
def join(self, args, sep = ""):
return sep.join([self._string, *args])
def __str__(self):
return self._string
a = StringPlus("a")
bc = a.join(["b", "c"], sep = "")
assert bc == "abc"
Как насчет того, чтобы присоединиться, не прибегая к внешним join?