Ошибка: TypeError: unsupported format string passed to Negate.__format__

Рейтинг: 0Ответов: 1Опубликовано: 25.03.2023

обучаюсь у Лутса, пошарил в инете ничего не нашел по данному вопросу, как решить данную проблему?

def square(arg):
    return arg ** 2  # Простые функции def или lambda

class Sum:
    def __init__(self, val):  # Вызываемые экземляры
        self.val = val

    def __call__(self, arg):
        return self.val * arg


class Product:
    def __init__(self, val):  # Свзвнные методы
        self.val = val

    def method(self, arg):
        return self.val * arg


sobject = Sum(2)
pobject = Product(3)
actions = [square, sobject, pobject.method]  # Функцияб экземляр, метод
for act in actions:  # Все три вызываются одинаково
    print(act(5))  # Вызов любого вызываемого объекта с одним аргументом
print(actions[-1](5))  # Идексы, генераторы, отображения
# Result - 15
print([act(5) for act in actions])
# Result - [25, 10, 15]
print(list(map(lambda act: act(5), actions)))


# Result - [25, 10, 15]
class Negate:
    def __init__(self, val):  # Классы - тоже вызываемые объекты
        self.val = -val  # Но вызываются для создания объектов

    def __repr__(self):  # Реализует вывод экземляра
        return str(self.val)


actions1 = [square, sobject, pobject.method, Negate]  # Вызвать класс тоже
for act1 in actions1:
    print(act1(5))
print([act1(5) for act1 in actions1])  # Вызовет __repr__, а не __str__!
# Result - [25, 10, 15, -5]
table = {act1(5): act for act1 in actions1}  # Генератор словарей
for (key, value) in table.items():
    print('{0:2} => {1}'.format(key, value))  # Метод str.format

Ошибка:

25 => <bound method Product.method of <__main__.Product object at 0x000001FB7613F650>>
10 => <bound method Product.method of <__main__.Product object at 0x000001FB7613F650>>
15 => <bound method Product.method of <__main__.Product object at 0x000001FB7613F650>>
Traceback (most recent call last):
  File "G:\Python\Обучение\Глава 30. Шаблоны проектирования с классами\sum.py", line 49, in <module>
    print('{0:2} => {1}'.format(key, value))  # Метод str.format
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: unsupported format string passed to Negate.__format__

Process finished with exit code 1

Ответы

▲ 1

Когда объект передается в метод str.format или функцию format, или при форматировании через f-строку, для форматирования этого объекта у него вызывается метод __format__, через параметр которого передается то, что в фигурных скобках после двоеточия:

class Test:
    def __format__(self, format_spec: str) -> str:
        print("format_spec:", repr(format_spec))
        return str(self)


"{0:some random staff}".format(Test())
# Выведет format_spec: 'some random staff'

Если метод __format__ не определен, он наследуется у object, и любое непустое значение format_spec будет вызывать ошибку:

class Test:
    pass


"{0:some random staff}".format(Test())
# TypeError: unsupported format string passed to Test.__format__

Соответствующий кусок документации:

https://docs.python.org/3/library/functions.html#format

A call to format(value, format_spec) is translated to type(value).__format__(value, format_spec) which bypasses the instance dictionary when searching for the value’s __format__() method. A TypeError exception is raised if the method search reaches object and the format_spec is non-empty, or if either the format_spec or the return value are not strings.

В данном случае ошибка как раз и возникает из-за того, что в строке форматирования стоит 2, а в классе Negate у вас метод __format__ не переопределен.

Можно или определить этот метод, или явно вызывать repr перед форматированием:

for (key, value) in table.items():
    print('{0:2} => {1}'.format(repr(key), value))