форматировать целые числа в последовательности (список, кортеж, множество) - PullRequest
3 голосов
/ 26 июня 2019

У меня есть класс, где один из членов является целочисленной последовательностью. Это может быть один из list, tuple или set. Когда в печати (__str__) экземпляры этого класса, мне нужно отформатировать целые числа, но сохранить тип последовательности.

В качестве примера у меня есть класс

class A:
    def __init__(self, seq):
        self.seq = seq

и три экземпляра

a = A(seq=tuple(range(5, 12)))
b = A(seq=list(range(17, 21)))
c = A(seq=set(range(26, 31)))

и я хотел бы получить следующий вывод для

print(a)  # A(seq=(0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b))
print(b)  # A(seq=[0x11, 0x12, 0x13, 0x14])
print(c)  # A(seq={0x1a, 0x1b, 0x1c, 0x1d, 0x1e})

Моя первая попытка была такая (и она не работает! Элементы представлены в виде строк).

class A:

    def __str__(self):
        seq2 = self.seq.__class__(f"0x{i:02x}" for i in self.seq)
        return f"A(seq={seq2})"

# A(seq=('0x05', '0x06', '0x07', '0x08', '0x09', '0x0a', '0x0b'))
# A(seq=['0x11', '0x12', '0x13', '0x14'])
# A(seq={'0x1b', '0x1c', '0x1d', '0x1a', '0x1e'})

Подход, который работает, но кажется очень неуклюжим, таков:

class A:

    def __str__(self):
        item_str = ", ".join(f"0x{i:02x}" for i in self.seq)
        if isinstance(self.seq, list):
            o, c = "[", "]"
        elif isinstance(self.seq, tuple):
            o, c = "(", ")"
        elif isinstance(self.seq, set):
            o, c = "{", "}"
        else:
            raise ValueError
        return f"A(seq={o}{item_str}{c})"

# A(seq=(0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b))
# A(seq=[0x11, 0x12, 0x13, 0x14])
# A(seq={0x1a, 0x1b, 0x1c, 0x1d, 0x1e})

Разве нет более элегантной версии этого? Или я должен подкласс list, tuple и set к версии, которая позволяет для параметров форматирования в __str__?

Ответы [ 2 ]

2 голосов
/ 26 июня 2019

Я бы использовал адресный словарь:

class A:
    def __str__(self):
        wrappers = {
            list : "[]",
            tuple: "()",
            set  : "{}",
        }
        item_str = ", ".join(f"0x{i:02x}" for i in self.seq)
        o, c = wrappers.get(type(self.seq), "||")
        return f"A(seq={o}{item_str}{c})"
2 голосов
/ 26 июня 2019

Просто используйте str.replace():

class A:
    def __init__(self, seq):
        self.seq = seq

    def __str__(self):
        seq2 = self.seq.__class__(f"0x{i:02x}" for i in self.seq)
        return f"A(seq={seq2})".replace("'", '')

a = A(seq=tuple(range(5, 12)))
b = A(seq=list(range(17, 21)))
c = A(seq=set(range(26, 31)))

print(a)
print(b)
print(c)

Печать:

A(seq=(0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b))
A(seq=[0x11, 0x12, 0x13, 0x14])
A(seq={0x1b, 0x1c, 0x1a, 0x1d, 0x1e})
...