Сделать пользовательский класс совместимым с `.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 есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
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"

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