[Python-ideas] Way to repeat other than "for _ in range(x)"

Joao S. O. Bueno jsbueno at python.org.br
Thu Mar 30 12:54:51 EDT 2017


On 30 March 2017 at 13:10, Markus Meskanen <markusmeskanen at gmail.com> wrote:
>
>
> On Mar 30, 2017 19:04, "Joao S. O. Bueno" <jsbueno at python.org.br> wrote:
>
> On 30 March 2017 at 10:51, Mark E. Haase <mehaase at gmail.com> wrote:
>> Your example is really repeating two things:
>>
>> d = [ [0 for _ in range(5)] for _ in range(10) ]
>>
>> But since list() uses * for repetition, you could write it more concisely
>> as:
>>
>> d = [[0] * 5] * 10]
>>
>> I'm not picking on your specific example. I am only pointing out that
>> Python
>> gives you the tools you need to build nice APIs. If repetition is an
>> important part of something you're working on, then consider using
>> itertools.repeat, writing your own domain-specific repeat() method, or
>> even
>> override * like list() does. One of the coolest aspects of Python is how a
>> relatively small set of abstractions can be combined to create lots of
>> useful behaviors.
>
> I find it weird that not the author, neither the previous repliers noticed
> that
> "a repetition other than a for with dummy variable" was already in plain
> sight,
> in the very example given.
> Of course one is also free to write [ [0 for _ in range(5)] for _ in
> range(10)] if he wishes so.
>
>
> Had you read all the replies, you'd see people (including me, OP) repeating
> this multiple times:
>
> d = [[0] * 5] * 10
>
> Creates a list of ten references *to the same list*. This means that if I
> mutate any of the sub lists in d, all of the sub lists get mutated. There
> would only be one sub list, just ten references to it.


Yes. Nonetheless, it is still repeating. Accepting a new way for doing
this would go from 2 ways with 2 semantics to 3 ways with two
different semantics.

And, all you need is to create a special class to actually dupicate
the list on multiplying - not a big deal:

In [76]: class D:
   ...:     def __init__(self, value):
   ...:         self.value = value
   ...:     def __rmul__(self, other):
   ...:         if hasattr(other, '__len__') and hasattr(other, '__add__'):
   ...:             result = deepcopy(other)
   ...:             for _ in range(1, self.value):
   ...:                 result += deepcopy(other)
   ...:             return result
   ...:         return NotImplemented
   ...:

In [77]: from copy import deepcopy

In [78]: a = [[0] * 5] * D(10)

In [79]: a[5][2]  = "*"

In [80]: a
Out[80]:
[[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, '*', 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0]]


More information about the Python-ideas mailing list