On 05/25/2018 10:13 AM, bartc wrote:
On 25/05/2018 17:58, Rob Gaddi wrote:

So, in the spirit of explicit being better than implicit, please assume that for actual implementation replicate would be a static method of actual list, rather than the conveniently executable hackjob below.

_list = list
_nodefault = object()

class list(_list):
   @staticmethod
   def replicate(*n, fill=_nodefault, call=list):

That seems to work, but the dimensions are created in reverse order to what I expected. Which is to have the order of indices corresponding to the order of dimensions. So:

  x=list.replicate(2,3,4)

  print (len(x))
  print (len(x[0]))
  print (len(x[0][0]))

Gives output of 4, 3, 2 rather than 2, 3, 4.

Which means that x[0][0][3] is a bounds error.


A fair point. Something about multidimensional arrays always makes me semi-dyslexic. And there I was wondering why making it work right had required I rip dimensions off the list from the end instead.

Corrected version below. list.replicate(3, 2) now means "3 of 2 of this" as one would expect. This is one of those days when doctest is my favorite thing about Python.

_list = list
_nodefault = object()

class list(_list):
  @staticmethod
  def replicate(*n, fill=_nodefault, call=list):
    """Return a list of specified dimensions.

    Fill and call can be used to prime the list with initial values, the
    default is to create a list of empty lists.

    Parameters:
      n : List of dimensions
      fill: If provided, the fill object is used in all locations.
      call: If fill is not provided, the result of call (a function of
      no arguments) is used in all locations.

    Example:
      >>> a = list.replicate(3, 2)
      >>> a
      [[[], []], [[], []], [[], []]]
      >>> a[0][0].append('a')
      >>> a
      [[['a'], []], [[], []], [[], []]]

      >>> b = list.replicate(3, 2, fill=[])
      >>> b
      [[[], []], [[], []], [[], []]]
      >>> b[0][0].append('a')
      >>> b
      [[['a'], ['a']], [['a'], ['a']], [['a'], ['a']]]

      >>> c = list.replicate(3, 2, call=dict)
      >>> c
      [[{}, {}], [{}, {}], [{}, {}]]
      >>> c[0][0]['swallow'] = 'unladen'
      >>> c
      [[{'swallow': 'unladen'}, {}], [{}, {}], [{}, {}]]

      >>> d = list.replicate(3, 2, fill=0)
      >>> d
      [[0, 0], [0, 0], [0, 0]]
      >>> d[0][0] = 5
      >>> d
      [[5, 0], [0, 0], [0, 0]]
    """

    if n:
      this = n[0]
      future = n[1:]
      return [
        list.replicate(*future, fill=fill, call=call)
          for _ in range(this)
      ]
    elif fill is _nodefault:
      return call()
    else:
      return fill


--
Rob Gaddi, Highland Technology -- www.highlandtechnology.com
Email address domain is currently out of order.  See above to fix.
--
https://mail.python.org/mailman/listinfo/python-list

Reply via email to