Возможно ли, чтобы класс определял результат для спецификатора формата %d?

#python #string #class #formatting

#python #строка #класс #форматирование

Вопрос:

У меня есть экземпляр класса A , переданный в качестве значения спецификатору формата %d при форматировании строки с использованием % оператора. Без какой-либо подготовки это приведет к следующему сообщению об ошибке: TypeError: %d format: a number is required, not A :

 class A: pass

'%d' % A()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: %d format: a number is required, not A
  

Если класс A определяет вызываемый метод __int__ , он вызывается:

 class A:
  def __int__(self):  return 42

'%d' % A()
'42'
  

В моем случае использования я хотел бы форматирование с %d помощью create a string представления для экземпляров моего класса, которые выглядят не как число (а вместо этого произвольная строка, подобная n/a , ²³ , или аналогичная).

Возможно ли это?

Я рассматривал возможность возврата другого специального объекта в __int__ методе, но это привело к появлению предупреждения (разрешен только возврат базовых целых чисел, все остальное может стать незаконным в более поздних версиях; Я пытаюсь использовать Python 3.7.4, кстати) и в конечном итоге безуспешно.

Я знаю, что это простая задача, используя __format__ метод в сочетании со '{0}'.format(a) способом форматирования строк, но это не то, о чем я прошу. Я специально и только спрашиваю о форматировании с использованием %d спецификатора в строке форматирования, используемой с % оператором.

Комментарии:

1.Нет, это не предусмотрено. %d явно означает «преобразовать значение в целое число, затем интерполировать целочисленное значение в строку»; и эта логика реализована в самом % операторе. Такая негибкость является одной из многих причин не использовать этот древний метод форматирования 🙂

2. Вы спрашиваете, как закодировать противоречие в определении языка. Это очень похоже на вопрос, как вы можете заставить переменные типа integer содержать строковые значения. Это не то, для чего он предназначен, и является нарушением его основного существования.

3. @Prune Я не вижу причин, по которым это должно чему-то противоречить. Может быть просто, что в случае %d применения case к определяемому пользователем объекту запрашивается специальный метод этого объекта для выполнения задания (например __percent_format__(specifier) ). Этот способ используется с более современными .format() , и я не вижу причин, по которым это не следует делать с более старым % форматированием оператора. На самом деле, его можно было бы даже добавить сегодня. Это все равно ничему не противоречило бы.

Ответ №1:

Печать строки с использованием оператора %d не будет работать. Насколько я знаю, нет встроенной функции для изменения этого. Однако, если вы хотите напечатать строковое представление объекта, существует три разных способа с использованием оператора по модулю (%).

  1. %s — возвращает строку с использованием встроенного метода str()
  2. %r — возвращает строку с использованием встроенного метода repr()
  3. %a — возвращает строку с использованием встроенного метода ascii()

Используя эти три, вы можете настроить строку, используя соответствующие им методы dunber. Например, если бы вы использовали %s, он использовал бы встроенный метод str() . Чтобы отредактировать то, что возвращает метод str(), вы должны поместить это в свое определение класса.

 def __str__(self):
    return "String Representation"
  

Документация python описывает, почему %d не может печатать строки идеально. Обязательно прокрутите страницу вниз до того места, где находится объяснение% (примерно на полпути вниз по странице).

Комментарии:

1. В моем случае библиотека (т. Е. Не Мой код и Не подлежит изменению) используется %d для форматирования предоставленных мной входных данных, и мне интересно, могу ли я ввести специальное значение n / a для недоступно. Это работает для всех вычислений, которые библиотека выполняет с предоставленными значениями (потому что класс, который я написал для n / a, Имеет __mul__ __add__ методы и т. Д. (все они снова возвращают объект n / a). Проблема по-прежнему заключается только в процентном форматировании.