Сделать пользовательский класс совместимым с `.join()`

У меня есть класс 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"

Любые подсказки?

Как насчет того, чтобы присоединиться, не прибегая к внешним join?

RomanPerekhrest 17.02.2023 16:12
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
Потяните за рычаг выброса энергососущих проектов
Потяните за рычаг выброса энергососущих проектов
На этой неделе моя команда отменила проект, над которым я работал. Неделя усилий пошла насмарку.
Инструменты для веб-скрапинга с открытым исходным кодом: Python Developer Toolkit
Инструменты для веб-скрапинга с открытым исходным кодом: Python Developer Toolkit
Веб-скрейпинг, как мы все знаем, это дисциплина, которая развивается с течением времени. Появляются все более сложные средства борьбы с ботами, а...
Библиотека для работы с мороженым
Библиотека для работы с мороженым
Лично я попрощался с операторами print() в python. Без шуток.
Эмиссия счетов-фактур с помощью Telegram - Python RPA (BotCity)
Эмиссия счетов-фактур с помощью Telegram - Python RPA (BotCity)
Привет, люди RPA, это снова я и я несу подарки! В очередном моем приключении о том, как создавать ботов для облегчения рутины. Вот, думаю, стоит...
Пошаговое руководство по созданию собственного Slackbot: От установки до развертывания
Пошаговое руководство по созданию собственного Slackbot: От установки до развертывания
Шаг 1: Создание приложения Slack Чтобы создать Slackbot, вам необходимо создать приложение Slack. Войдите в свою учетную запись Slack и перейдите на...
0
1
54
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Str.join необходимо передать итерацию строк, поэтому это невозможно сделать без преобразования каждого элемента в list.

"".join(map(str, [a, "b"])) 
# or
"".join(str(x) for x in [a, "b"])

Однако изменение определения класса на подкласс str может позволить этому работать без ручного преобразования.

class StringPlus(str):

Не вариант, так как у меня нет доступа к библиотеке, которая joins.

Nico Schlömer 17.02.2023 15:43

@NicoSchlömer Тогда вы можете попробовать создать подкласс str.

Unmitigated 17.02.2023 15:44

Это, наверное, решение. Я помню, что у меня были проблемы с этим, хотя. Позвольте мне поиграть с ним снова.

Nico Schlömer 17.02.2023 15:45
Ответ принят как подходящий

Наследовать 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"

Другие вопросы по теме