Lazy format strings - Utilities

Skip to content
Back to top
View this page
Edit this page

# Lazy format strings

class sage.misc.lazy_format.LazyFormat

  Bases: `str`

  Lazy format strings.

  Note

  We recommend to use `sage.misc.lazy_string.lazy_string()` instead, which is both faster and more flexible.

  An instance of `LazyFormat` behaves like a usual format string, except that the evaluation of the `__repr__` method of the formatted arguments it postponed until actual printing.

  EXAMPLES:

  Under normal circumstances, `Lazyformat` strings behave as usual:

  Sage

      sage: from sage.misc.lazy_format import LazyFormat
      sage: LazyFormat("Got `%s`; expected a list")%3
      Got `3`; expected a list
      sage: LazyFormat("Got `%s`; expected %s")%(3, 2/3)
      Got `3`; expected 2/3

  Python

      >>> from sage.all import *
      >>> from sage.misc.lazy_format import LazyFormat
      >>> LazyFormat("Got `%s`; expected a list")%Integer(3)
      Got `3`; expected a list
      >>> LazyFormat("Got `%s`; expected %s")%(Integer(3), Integer(2)/Integer(3))
      Got `3`; expected 2/3

  To demonstrate the laziness, let us build an object with a broken `__repr__` method:

  Sage

      sage: class IDontLikeBeingPrinted():
      ....:     def __repr__(self):
      ....:         raise ValueError("do not ever try to print me")

  [Python]

      >>> from sage.all import *
      >>> class IDontLikeBeingPrinted():
      ...     def __repr__(self):
      ...         raise ValueError("do not ever try to print me")

  There is no error when binding a lazy format with the broken object:

  Sage

      sage: lf = LazyFormat("<%s>")%IDontLikeBeingPrinted()

  Python

      >>> from sage.all import *
      >>> lf = LazyFormat("<%s>")%IDontLikeBeingPrinted()

  The error only occurs upon printing:

  Sage

      sage: lf
      <repr(<sage.misc.lazy_format.LazyFormat at 0x...>) failed: ValueError: do not ever try to print me>

  [Python]

      >>> from sage.all import *
      >>> lf
      <repr(<sage.misc.lazy_format.LazyFormat at 0x...>) failed: ValueError: do not ever try to print me>

  Common use case:

  Most of the time, `__repr__` methods are only called during user interaction, and therefore need not be fast; and indeed there are objects `x` in Sage such `x.__repr__()` is time consuming.

  There are however some uses cases where many format strings are constructed but not actually printed. This includes error handling messages in `unittest` or `TestSuite` executions:

  Sage

      sage: QQ._tester().assertIn(0, QQ,
      ....:                "%s doesn't contain 0"%QQ)

  Python

      >>> from sage.all import *
      >>> QQ._tester().assertIn(Integer(0), QQ,
      ...                "%s doesn't contain 0"%QQ)

  In the above `QQ.__repr__()` has been called, and the result immediately discarded. To demonstrate this we replace `QQ` in the format string argument with our broken object:

  Sage

      sage: QQ._tester().assertTrue(True,
      ....:                "%s doesn't contain 0"%IDontLikeBeingPrinted())
      Traceback (most recent call last):
      ...
      ValueError: do not ever try to print me

  [Python]

      >>> from sage.all import *
      >>> QQ._tester().assertTrue(True,
      ...                "%s doesn't contain 0"%IDontLikeBeingPrinted())
      Traceback (most recent call last):
      ...
      ValueError: do not ever try to print me

  This behavior can induce major performance penalties when testing. Note that this issue does not impact the usual assert:

  Sage

      sage: assert True, "%s is wrong"%IDontLikeBeingPrinted()

  Python

      >>> from sage.all import *
      >>> assert True, "%s is wrong"%IDontLikeBeingPrinted()

  We now check that `LazyFormat` indeed solves the assertion problem:

  Sage

      sage: QQ._tester().assertTrue(True,
      ....:               LazyFormat("%s is wrong")%IDontLikeBeingPrinted())
      sage: QQ._tester().assertTrue(False,
      ....:               LazyFormat("%s is wrong")%IDontLikeBeingPrinted())
      Traceback (most recent call last):
      ...
      AssertionError: ...

  [Python]

      >>> from sage.all import *
      >>> QQ._tester().assertTrue(True,
      ...               LazyFormat("%s is wrong")%IDontLikeBeingPrinted())
      >>> QQ._tester().assertTrue(False,
      ...               LazyFormat("%s is wrong")%IDontLikeBeingPrinted())
      Traceback (most recent call last):
      ...
      AssertionError: ...