[Python-ideas] Set starting point for itertools.product()

Ronie Martinez ronmarti18 at gmail.com
Thu Oct 25 22:20:35 EDT 2018


Hi Steve,

I tried this when writing DocCron <https://github.com/Code-ReaQtor/DocCron>but
it will not work correctly.

Suppose we have minutes with range 0-59 and seconds with range 0-59 but
starting at, say, 5:

When the seconds value reaches 59, on the next iteration the minute value
should increase by 1 (or back to zero) but it will not work that way since
the next rotation will be at 4 transitioning to 5.

So the correct solution is not modifying any of the arrangements.

Best Regards,
Ronie





On Thu, Oct 25, 2018 at 7:31 PM Steven D'Aprano <steve at pearwood.info> wrote:

> On Thu, Oct 25, 2018 at 02:31:05PM +0800, Ronie Martinez wrote:
>
> > def main():
> >     datetime_odometer = itertools.product(
> >         range(2018, 10_000),  # year
> >         range(1, 13),  # month
> >         range(1, 31),  # days
> >         range(0, 24),  # hours
> >         range(0, 60),  # minutes
> >         range(0, 60)  # seconds
> >     )
>
> When you talked about datetime, I thought you meant actual datetime
> objects. The above is buggy: it ignores the 31st day of January, etc,
> but includes February 29 and 30 every year.
>
>
> >     datetime_of_interest = (2050, 6, 15, 10, 5, 0)
> >
> >     for i in datetime_odometer:
> >         if i == datetime_of_interest: # target start time
> >             break
>
> In the most general case, there is no way to jump into the middle of an
> arbitrary iterator, except to start at the beginning and compute the
> values until you see the one that you want. Arbitrary iterators compute
> their values on request, and there is no way to jump ahead except by
> inspecting each value in turn, skipping the ones you don't want.
>
> So unless I have missed something, I think what you are asking for is
> impossible except for special cases like lists.
>
> But in *this* case, modelling an odometer, that special case works:
>
> def rotate(iterable, position):
>     L = list(iterable)
>     return L[position:] + L[:position]
>
> Which gives us this:
>
> py> months = rotate(range(1, 13), 5)
> py> months
> [6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5]
>
> Now pass that to itertools.product.
>
> In other words, I think that the right solution here is to construct
> your iterables to start at the position you want, rather than expect
> product() to jump into the middle of the sequence. (Which may not be
> possible.)
>
>
>
> --
> Steve
> _______________________________________________
> Python-ideas mailing list
> Python-ideas at python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20181026/50bae306/attachment-0001.html>


More information about the Python-ideas mailing list