Miscellaneous functions - Utilities

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

# Miscellaneous functions

AUTHORS:

- William Stein

- William Stein (2006-04-26): added workaround for Windows where most users’ home directory has a space in it.

- Robert Bradshaw (2007-09-20): Ellipsis range/iterator.

sage.misc.misc.compose(f, g)

  Return the composition of one-variable functions: \(f \circ g\).

  See also `nest()`

  INPUT:

  - `f` – a function of one variable

  - `g` – another function of one variable

  OUTPUT: a function, such that compose(f,g)(x) = f(g(x))

  EXAMPLES:

  Sage

      sage: def g(x): return 3*x
      sage: def f(x): return x + 1
      sage: h1 = compose(f, g)
      sage: h2 = compose(g, f)
      sage: _ = var('x')                                                              # needs sage.symbolic
      sage: h1(x)                                                                     # needs sage.symbolic
      3*x + 1
      sage: h2(x)                                                                     # needs sage.symbolic
      3*x + 3

  Python

      >>> from sage.all import *
      >>> def g(x): return Integer(3)*x
      >>> def f(x): return x + Integer(1)
      >>> h1 = compose(f, g)
      >>> h2 = compose(g, f)
      >>> _ = var('x')                                                              # needs sage.symbolic
      >>> h1(x)                                                                     # needs sage.symbolic
      3*x + 1
      >>> h2(x)                                                                     # needs sage.symbolic
      3*x + 3

  Sage

      sage: _ = function('f g')                                                       # needs sage.symbolic
      sage: _ = var('x')                                                              # needs sage.symbolic
      sage: compose(f, g)(x)                                                          # needs sage.symbolic
      f(g(x))

  [Python]

      >>> from sage.all import *
      >>> _ = function('f g')                                                       # needs sage.symbolic
      >>> _ = var('x')                                                              # needs sage.symbolic
      >>> compose(f, g)(x)                                                          # needs sage.symbolic
      f(g(x))

sage.misc.misc.exactly_one_is_true(iterable)

  Return whether exactly one element of `iterable` evaluates `True`.

  INPUT:

  - `iterable` – an iterable object

  OUTPUT: boolean

  Note

  The implementation is suggested by stackoverflow entry.

  EXAMPLES:

  Sage

      sage: from sage.misc.misc import exactly_one_is_true
      sage: exactly_one_is_true([])
      False
      sage: exactly_one_is_true([True])
      True
      sage: exactly_one_is_true([False])
      False
      sage: exactly_one_is_true([True, True])
      False
      sage: exactly_one_is_true([False, True])
      True
      sage: exactly_one_is_true([True, False, True])
      False
      sage: exactly_one_is_true([False, True, False])
      True

  Python

      >>> from sage.all import *
      >>> from sage.misc.misc import exactly_one_is_true
      >>> exactly_one_is_true([])
      False
      >>> exactly_one_is_true([True])
      True
      >>> exactly_one_is_true([False])
      False
      >>> exactly_one_is_true([True, True])
      False
      >>> exactly_one_is_true([False, True])
      True
      >>> exactly_one_is_true([True, False, True])
      False
      >>> exactly_one_is_true([False, True, False])
      True

sage.misc.misc.exists(S, P)

  If S contains an element x such that P(x) is `True`, this function returns `True` and the element x. Otherwise it returns `False` and None.

  Note that this function is NOT suitable to be used in an if-statement or in any place where a boolean expression is expected. For those situations, use the Python built-in

  any(P(x) for x in S)

  INPUT:

  - `S` – object (that supports enumeration)

  - `P` – function that returns `True` or `False`

  OUTPUT:

  - `bool` – whether or not P is `True` for some element x of S

  - `object` – x

  EXAMPLES: lambda functions are very useful when using the exists function:

  Sage

      sage: exists([1,2,5], lambda x : x > 7)
      (False, None)
      sage: exists([1,2,5], lambda x : x > 3)
      (True, 5)

  Python

      >>> from sage.all import *
      >>> exists([Integer(1),Integer(2),Integer(5)], lambda x : x > Integer(7))
      (False, None)
      >>> exists([Integer(1),Integer(2),Integer(5)], lambda x : x > Integer(3))
      (True, 5)

  The following example is similar to one in the MAGMA handbook. We check whether certain integers are a sum of two (small) cubes:

  Sage

      sage: cubes = [t**3 for t in range(-10,11)]
      sage: exists([(x,y) for x in cubes for y in cubes], lambda v : v[0]+v[1] == 218)
      (True, (-125, 343))
      sage: exists([(x,y) for x in cubes for y in cubes], lambda v : v[0]+v[1] == 219)
      (False, None)

  [Python]

      >>> from sage.all import *
      >>> cubes = [t**Integer(3) for t in range(-Integer(10),Integer(11))]
      >>> exists([(x,y) for x in cubes for y in cubes], lambda v : v[Integer(0)]+v[Integer(1)] == Integer(218))
      (True, (-125, 343))
      >>> exists([(x,y) for x in cubes for y in cubes], lambda v : v[Integer(0)]+v[Integer(1)] == Integer(219))
      (False, None)

sage.misc.misc.forall(S, P)

  If \(P(x)\) is true every x in S, return `True` and `None`. If there is some element x in S such that P is not `True`, return `False` and \(x\).

  Note that this function is NOT suitable to be used in an if-statement or in any place where a boolean expression is expected. For those situations, use the Python built-in

  all(P(x) for x in S)

  INPUT:

  - `S` – object (that supports enumeration)

  - `P` – function that returns `True` or `False`

  OUTPUT:

  - `bool` – whether or not P is `True` for all elements of S

  - `object` – x

  EXAMPLES: lambda functions are very useful when using the forall function. As a toy example we test whether certain integers are greater than 3.

  Sage

      sage: forall([1,2,5], lambda x : x > 3)
      (False, 1)
      sage: forall([1,2,5], lambda x : x > 0)
      (True, None)

  Python

      >>> from sage.all import *
      >>> forall([Integer(1),Integer(2),Integer(5)], lambda x : x > Integer(3))
      (False, 1)
      >>> forall([Integer(1),Integer(2),Integer(5)], lambda x : x > Integer(0))
      (True, None)

  Next we ask whether every positive integer less than 100 is a product of at most 2 prime factors:

  Sage

      sage: forall(range(1,100),  lambda n : len(factor(n)) <= 2)
      (False, 30)

  [Python]

      >>> from sage.all import *
      >>> forall(range(Integer(1),Integer(100)),  lambda n : len(factor(n)) <= Integer(2))
      (False, 30)

  The answer is no, and 30 is a counterexample. However, every positive integer 100 is a product of at most 3 primes.

  Sage

      sage: forall(range(1,100),  lambda n : len(factor(n)) <= 3)
      (True, None)

  Python

      >>> from sage.all import *
      >>> forall(range(Integer(1),Integer(100)),  lambda n : len(factor(n)) <= Integer(3))
      (True, None)

sage.misc.misc.get_main_globals()

  Return the main global namespace.

  EXAMPLES:

  Sage

      sage: from sage.misc.misc import get_main_globals
      sage: G = get_main_globals()
      sage: bla = 1
      sage: G['bla']
      1
      sage: bla = 2
      sage: G['bla']
      2
      sage: G['ble'] = 5
      sage: ble
      5

  Python

      >>> from sage.all import *
      >>> from sage.misc.misc import get_main_globals
      >>> G = get_main_globals()
      >>> bla = Integer(1)
      >>> G['bla']
      1
      >>> bla = Integer(2)
      >>> G['bla']
      2
      >>> G['ble'] = Integer(5)
      >>> ble
      5

  This is analogous to `globals()`, except that it can be called from any function, even if it is in a Python module:

  Sage

      sage: def f():
      ....:     G = get_main_globals()
      ....:     assert G['bli'] == 14
      ....:     G['blo'] = 42
      sage: bli = 14
      sage: f()
      sage: blo
      42

  [Python]

      >>> from sage.all import *
      >>> def f():
      ...     G = get_main_globals()
      ...     assert G['bli'] == Integer(14)
      ...     G['blo'] = Integer(42)
      >>> bli = Integer(14)
      >>> f()
      >>> blo
      42

  ALGORITHM:

  The main global namespace is discovered by going up the frame stack until the frame for the `__main__` module is found. Should this frame not be found (this should not occur in normal operation), an exception “ValueError: call stack is not deep enough” will be raised by `_getframe`.

  See `inject_variable_test()` for a real test that this works within deeply nested calls in a function defined in a Python module.

sage.misc.misc.increase_recursion_limit(*args, **kwds)

  Context manager to temporarily change the Python maximum recursion depth.

  INPUT:

  - `increment` – increment to add to the current limit

  EXAMPLES:

  Sage

      sage: from sage.misc.misc import increase_recursion_limit
      sage: def rec(n): None if n == 0 else rec(n-1)
      sage: rec(10000)
      Traceback (most recent call last):
      ...
      RecursionError: maximum recursion depth exceeded...
      sage: with increase_recursion_limit(10000): rec(10000)
      sage: rec(10000)
      Traceback (most recent call last):
      ...
      RecursionError: maximum recursion depth exceeded...

  Python

      >>> from sage.all import *
      >>> from sage.misc.misc import increase_recursion_limit
      >>> def rec(n): None if n == Integer(0) else rec(n-Integer(1))
      >>> rec(Integer(10000))
      Traceback (most recent call last):
      ...
      RecursionError: maximum recursion depth exceeded...
      >>> with increase_recursion_limit(Integer(10000)): rec(Integer(10000))
      >>> rec(Integer(10000))
      Traceback (most recent call last):
      ...
      RecursionError: maximum recursion depth exceeded...

sage.misc.misc.inject_variable(name, value, warn=True)

  Inject a variable into the main global namespace.

  INPUT:

  - `name` – string

  - `value` – anything

  - `warn` – boolean (default: `False`)

  EXAMPLES:

  Sage

      sage: from sage.misc.misc import inject_variable
      sage: inject_variable("a", 314)
      sage: a
      314

  Python

      >>> from sage.all import *
      >>> from sage.misc.misc import inject_variable
      >>> inject_variable("a", Integer(314))
      >>> a
      314

  A warning is issued the first time an existing value is overwritten:

  Sage

      sage: inject_variable("a", 271)
      doctest:...: RuntimeWarning: redefining global value `a`
      sage: a
      271
      sage: inject_variable("a", 272)
      sage: a
      272

  [Python]

      >>> from sage.all import *
      >>> inject_variable("a", Integer(271))
      doctest:...: RuntimeWarning: redefining global value `a`
      >>> a
      271
      >>> inject_variable("a", Integer(272))
      >>> a
      272

  That’s because warn seem to not reissue twice the same warning:

  Sage

      sage: from warnings import warn
      sage: warn("blah")
      doctest:...: UserWarning: blah
      sage: warn("blah")

  Python

      >>> from sage.all import *
      >>> from warnings import warn
      >>> warn("blah")
      doctest:...: UserWarning: blah
      >>> warn("blah")

  Warnings can be disabled:

  Sage

      sage: b = 3
      sage: inject_variable("b", 42, warn=False)
      sage: b
      42

  [Python]

      >>> from sage.all import *
      >>> b = Integer(3)
      >>> inject_variable("b", Integer(42), warn=False)
      >>> b
      42

  Use with care!

sage.misc.misc.inject_variable_test(name, value, depth)

  A function for testing deep calls to `inject_variable`.

  EXAMPLES:

  Sage

      sage: from sage.misc.misc import inject_variable_test
      sage: inject_variable_test("a0", 314, 0)
      sage: a0
      314
      sage: inject_variable_test("a1", 314, 1)
      sage: a1
      314
      sage: inject_variable_test("a2", 314, 2)
      sage: a2
      314
      sage: inject_variable_test("a2", 271, 2)
      doctest:...: RuntimeWarning: redefining global value `a2`
      sage: a2
      271

  Python

      >>> from sage.all import *
      >>> from sage.misc.misc import inject_variable_test
      >>> inject_variable_test("a0", Integer(314), Integer(0))
      >>> a0
      314
      >>> inject_variable_test("a1", Integer(314), Integer(1))
      >>> a1
      314
      >>> inject_variable_test("a2", Integer(314), Integer(2))
      >>> a2
      314
      >>> inject_variable_test("a2", Integer(271), Integer(2))
      doctest:...: RuntimeWarning: redefining global value `a2`
      >>> a2
      271

sage.misc.misc.is_in_string(line, pos)

  Return `True` if the character at position `pos` in `line` occurs within a string.

  EXAMPLES:

  Sage

      sage: from sage.misc.misc import is_in_string
      sage: line = 'test(\'#\')'
      sage: is_in_string(line, line.rfind('#'))
      True
      sage: is_in_string(line, line.rfind(')'))
      False

  Python

      >>> from sage.all import *
      >>> from sage.misc.misc import is_in_string
      >>> line = 'test(\'#\')'
      >>> is_in_string(line, line.rfind('#'))
      True
      >>> is_in_string(line, line.rfind(')'))
      False

sage.misc.misc.is_iterator(it)

  Test if it is an iterator.

  The mantra `if hasattr(it, 'next')` was used to tests if `it` is an iterator. This is not quite correct since `it` could have a `next` methods with a different semantic.

  EXAMPLES:

  Sage

      sage: it = iter([1,2,3])
      sage: is_iterator(it)
      True

      sage: class wrong():
      ....:    def __init__(self): self.n = 5
      ....:    def __next__(self):
      ....:        self.n -= 1
      ....:        if self.n == 0: raise StopIteration
      ....:        return self.n
      sage: x = wrong()
      sage: is_iterator(x)
      False
      sage: list(x)
      Traceback (most recent call last):
      ...
      TypeError: 'wrong' object is not iterable

      sage: class good(wrong):
      ....:    def __iter__(self): return self
      sage: x = good()
      sage: is_iterator(x)
      True
      sage: list(x)
      [4, 3, 2, 1]

      sage: P = Partitions(3)                                                         # needs sage.combinat
      sage: is_iterator(P)                                                            # needs sage.combinat
      False
      sage: is_iterator(iter(P))                                                      # needs sage.combinat
      True

  Python

      >>> from sage.all import *
      >>> it = iter([Integer(1),Integer(2),Integer(3)])
      >>> is_iterator(it)
      True

      >>> class wrong():
      ...    def __init__(self): self.n = Integer(5)
      ...    def __next__(self):
      ...        self.n -= Integer(1)
      ...        if self.n == Integer(0): raise StopIteration
      ...        return self.n
      >>> x = wrong()
      >>> is_iterator(x)
      False
      >>> list(x)
      Traceback (most recent call last):
      ...
      TypeError: 'wrong' object is not iterable

      >>> class good(wrong):
      ...    def __iter__(self): return self
      >>> x = good()
      >>> is_iterator(x)
      True
      >>> list(x)
      [4, 3, 2, 1]

      >>> P = Partitions(Integer(3))                                                         # needs sage.combinat
      >>> is_iterator(P)                                                            # needs sage.combinat
      False
      >>> is_iterator(iter(P))                                                      # needs sage.combinat
      True

sage.misc.misc.is_sublist(X, Y)

  Test whether `X` is a sublist of `Y`.

  EXAMPLES:

  Sage

      sage: from sage.misc.misc import is_sublist
      sage: S = [1, 7, 3, 4, 18]
      sage: is_sublist([1, 7], S)
      True
      sage: is_sublist([1, 3, 4], S)
      True
      sage: is_sublist([1, 4, 3], S)
      False
      sage: is_sublist(S, S)
      True

  Python

      >>> from sage.all import *
      >>> from sage.misc.misc import is_sublist
      >>> S = [Integer(1), Integer(7), Integer(3), Integer(4), Integer(18)]
      >>> is_sublist([Integer(1), Integer(7)], S)
      True
      >>> is_sublist([Integer(1), Integer(3), Integer(4)], S)
      True
      >>> is_sublist([Integer(1), Integer(4), Integer(3)], S)
      False
      >>> is_sublist(S, S)
      True

sage.misc.misc.nest(f, n, x)

  Return \(f(f(...f(x)...))\), where the composition occurs n times.

  See also `compose()` and `self_compose()`

  INPUT:

  - `f` – a function of one variable

  - `n` – nonnegative integer

  - `x` – any input for \(f\)

  OUTPUT: \(f(f(...f(x)...))\), where the composition occurs n times

  EXAMPLES:

  Sage

      sage: def f(x): return x^2 + 1
      sage: x = var('x')                                                              # needs sage.symbolic
      sage: nest(f, 3, x)                                                             # needs sage.symbolic
      ((x^2 + 1)^2 + 1)^2 + 1

  Python

      >>> from sage.all import *
      >>> def f(x): return x**Integer(2) + Integer(1)
      >>> x = var('x')                                                              # needs sage.symbolic
      >>> nest(f, Integer(3), x)                                                             # needs sage.symbolic
      ((x^2 + 1)^2 + 1)^2 + 1

  Sage

      sage: _ = function('f')                                                         # needs sage.symbolic
      sage: _ = var('x')                                                              # needs sage.symbolic
      sage: nest(f, 10, x)                                                            # needs sage.symbolic
      f(f(f(f(f(f(f(f(f(f(x))))))))))

  [Python]

      >>> from sage.all import *
      >>> _ = function('f')                                                         # needs sage.symbolic
      >>> _ = var('x')                                                              # needs sage.symbolic
      >>> nest(f, Integer(10), x)                                                            # needs sage.symbolic
      f(f(f(f(f(f(f(f(f(f(x))))))))))

  Sage

      sage: _ = function('f')                                                         # needs sage.symbolic
      sage: _ = var('x')                                                              # needs sage.symbolic
      sage: nest(f, 0, x)                                                             # needs sage.symbolic
      x

  Python

      >>> from sage.all import *
      >>> _ = function('f')                                                         # needs sage.symbolic
      >>> _ = var('x')                                                              # needs sage.symbolic
      >>> nest(f, Integer(0), x)                                                             # needs sage.symbolic
      x

sage.misc.misc.newton_method_sizes(N)

  Return a sequence of integers \(1 = a_1 \leq a_2 \leq \cdots \leq a_n = N\) such that \(a_j = \lceil a_{j+1} / 2 \rceil\) for all \(j\).

  This is useful for Newton-style algorithms that double the precision at each stage. For example if you start at precision 1 and want an answer to precision 17, then it’s better to use the intermediate stages 1, 2, 3, 5, 9, 17 than to use 1, 2, 4, 8, 16, 17.

  INPUT:

  - `N` – positive integer

  EXAMPLES:

  Sage

      sage: newton_method_sizes(17)
      [1, 2, 3, 5, 9, 17]
      sage: newton_method_sizes(16)
      [1, 2, 4, 8, 16]
      sage: newton_method_sizes(1)
      [1]

  Python

      >>> from sage.all import *
      >>> newton_method_sizes(Integer(17))
      [1, 2, 3, 5, 9, 17]
      >>> newton_method_sizes(Integer(16))
      [1, 2, 4, 8, 16]
      >>> newton_method_sizes(Integer(1))
      [1]

  AUTHORS:

  - David Harvey (2006-09-09)

sage.misc.misc.pad_zeros(s, size=3)

  EXAMPLES:

  Sage

      sage: pad_zeros(100)
      '100'
      sage: pad_zeros(10)
      '010'
      sage: pad_zeros(10, 5)
      '00010'
      sage: pad_zeros(389, 5)
      '00389'
      sage: pad_zeros(389, 10)
      '0000000389'

  Python

      >>> from sage.all import *
      >>> pad_zeros(Integer(100))
      '100'
      >>> pad_zeros(Integer(10))
      '010'
      >>> pad_zeros(Integer(10), Integer(5))
      '00010'
      >>> pad_zeros(Integer(389), Integer(5))
      '00389'
      >>> pad_zeros(Integer(389), Integer(10))
      '0000000389'

sage.misc.misc.random_sublist(X, s)

  Return a pseudo-random sublist of the list X where the probability of including a particular element is s.

  INPUT:

  - `X` – list

  - `s` – floating point number between 0 and 1

  OUTPUT: list

  EXAMPLES:

  Sage

      sage: from sage.misc.misc import is_sublist
      sage: S = [1,7,3,4,18]
      sage: sublist = random_sublist(S, 0.5); sublist  # random
      [1, 3, 4]
      sage: is_sublist(sublist, S)
      True
      sage: sublist = random_sublist(S, 0.5); sublist  # random
      [1, 3]
      sage: is_sublist(sublist, S)
      True

  Python

      >>> from sage.all import *
      >>> from sage.misc.misc import is_sublist
      >>> S = [Integer(1),Integer(7),Integer(3),Integer(4),Integer(18)]
      >>> sublist = random_sublist(S, RealNumber('0.5')); sublist  # random
      [1, 3, 4]
      >>> is_sublist(sublist, S)
      True
      >>> sublist = random_sublist(S, RealNumber('0.5')); sublist  # random
      [1, 3]
      >>> is_sublist(sublist, S)
      True

sage.misc.misc.run_once(func)

  Run a function (successfully) only once.

  The running can be reset by setting the `has_run` attribute to False

sage.misc.misc.some_tuples(elements, repeat, bound, max_samples=None)

  Return an iterator over at most `bound` number of `repeat`-tuples of `elements`.

  INPUT:

  - `elements` – an iterable

  - `repeat` – integer (default: `None`); the length of the tuples to be returned. If `None`, just returns entries from `elements`.

  - `bound` – the maximum number of tuples returned (ignored if `max_samples` given)

  - `max_samples` – nonnegative integer (default: `None`); if given, then a sample of the possible tuples will be returned, instead of the first few in the standard order

  OUTPUT:

  If `max_samples` is not provided, an iterator over the first `bound` tuples of length `repeat`, in the standard nested-for-loop order.

  If `max_samples` is provided, a list of at most `max_samples` tuples, sampled uniformly from the possibilities. In this case, `elements` must be finite.

sage.misc.misc.strunc(s, n=60)

  Truncate at first space after position n, adding ‘…’ if nontrivial truncation.

sage.misc.misc.try_read(obj, splitlines=False)

  Determine if a given object is a readable file-like object and if so read and return its contents.

  That is, the object has a callable method named `read()` which takes no arguments (except `self`) then the method is executed and the contents are returned.

  Alternatively, if the `splitlines=True` is given, first `splitlines()` is tried, then if that fails `read().splitlines()`.

  If either method fails, `None` is returned.

  INPUT:

  - `obj` – typically a \(file\) or \(io.BaseIO\) object, but any other object with a `read()` method is accepted

  - `splitlines` – boolean (default: `False`); if `True`, return a list of lines instead of a string

  EXAMPLES:

  Sage

      sage: import io
      sage: filename = tmp_filename()
      sage: from sage.misc.misc import try_read
      sage: with open(filename, 'w') as fobj:
      ....:     _ = fobj.write('a\nb\nc')
      sage: with open(filename) as fobj:
      ....:     print(try_read(fobj))
      a
      b
      c
      sage: with open(filename) as fobj:
      ....:     try_read(fobj, splitlines=True)
      ['a\n', 'b\n', 'c']

  Python

      >>> from sage.all import *
      >>> import io
      >>> filename = tmp_filename()
      >>> from sage.misc.misc import try_read
      >>> with open(filename, 'w') as fobj:
      ...     _ = fobj.write('a\nb\nc')
      >>> with open(filename) as fobj:
      ...     print(try_read(fobj))
      a
      b
      c
      >>> with open(filename) as fobj:
      ...     try_read(fobj, splitlines=True)
      ['a\n', 'b\n', 'c']

  The following example is identical to the above example on Python 3, but different on Python 2 where `open != io.open`:

  Sage

      sage: with io.open(filename) as fobj:
      ....:     print(try_read(fobj))
      a
      b
      c

  [Python]

      >>> from sage.all import *
      >>> with io.open(filename) as fobj:
      ...     print(try_read(fobj))
      a
      b
      c

  I/O buffers:

  Sage

      sage: buf = io.StringIO('a\nb\nc')
      sage: print(try_read(buf))
      a
      b
      c
      sage: _ = buf.seek(0); try_read(buf, splitlines=True)
      ['a\n', 'b\n', 'c']
      sage: buf = io.BytesIO(b'a\nb\nc')
      sage: try_read(buf) == b'a\nb\nc'
      True
      sage: _ = buf.seek(0)
      sage: try_read(buf, splitlines=True) == [b'a\n', b'b\n', b'c']
      True

  Python

      >>> from sage.all import *
      >>> buf = io.StringIO('a\nb\nc')
      >>> print(try_read(buf))
      a
      b
      c
      >>> _ = buf.seek(Integer(0)); try_read(buf, splitlines=True)
      ['a\n', 'b\n', 'c']
      >>> buf = io.BytesIO(b'a\nb\nc')
      >>> try_read(buf) == b'a\nb\nc'
      True
      >>> _ = buf.seek(Integer(0))
      >>> try_read(buf, splitlines=True) == [b'a\n', b'b\n', b'c']
      True

  Custom readable:

  Sage

      sage: class MyFile():
      ....:     def read(self): return 'Hello world!'
      sage: try_read(MyFile())
      'Hello world!'
      sage: try_read(MyFile(), splitlines=True)
      ['Hello world!']

  [Python]

      >>> from sage.all import *
      >>> class MyFile():
      ...     def read(self): return 'Hello world!'
      >>> try_read(MyFile())
      'Hello world!'
      >>> try_read(MyFile(), splitlines=True)
      ['Hello world!']

  Not readable:

  Sage

      sage: try_read(1) is None
      True

  Python

      >>> from sage.all import *
      >>> try_read(Integer(1)) is None
      True

sage.misc.misc.word_wrap(s, ncols=85)