[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