Python生成器返回一系列次数

时间:2012-01-31 04:01:02

标签: python generator

我希望这不是Python生成器的能力之外的东西,但是我想构建一个,这样每次调用该函数时,它都会在下一分钟返回到结束时间。

因此该函数读取开始和结束时间,并以分钟为单位返回时间,直到覆盖其间的所有时间。

如何实施? TIA

3 个答案:

答案 0 :(得分:5)

datetime module非常棒。您需要了解两种数据类型:datetimetimedeltadatetime是一个时间点,而timedelta是一段时间。基本上,我在这里要做的是一次开始并一次结束(作为datetime对象),并逐步加1分钟。

这显然需要注意,你必须弄清楚如何将你的开始和结束时间变成datetime。有多种方法可以执行此操作:通过the constructorright nowUTC timestamp等等。

import datetime

def minute_range(start, end, step=1):
   cur = start
   while cur < end:
      yield cur
      cur += datetime.timedelta(minutes=step)

答案 1 :(得分:1)

因为更少的代码行总是更好(tm):

def minutes(s, e):
    secs = (e - s).seconds 
    return (s + datetime.timedelta(minutes = x) for x in xrange(secs / 60 + 1))

像这样使用:

>>> today = datetime.datetime(2012, 1, 31, 15, 20)
>>> for m in minutes(today, today + datetime.timedelta(minutes = 5)):
...     print m
2012-01-31 15:20:00
2012-01-31 15:21:00
2012-01-31 15:22:00
2012-01-31 15:23:00
2012-01-31 15:24:00
2012-01-31 15:25:00

答案 2 :(得分:0)

这是我用于此目的的发电机。它可以被增强以在一段时间后停止,或者你可以将这个逻辑保留在你的调用代码中,或者在其他一些迭代器中。

import time

def sleep_gen(period):
    """Generator, returning not sooner, then period seconds since last call.

    returned value: time of next planned start (no need to use this value)
    """
    next_time = 0
    while True:
        now = time.time()
        sleep_time = max(next_time - now, 0)
        next_time = now + sleep_time + period
        time.sleep(sleep_time)
        yield next_time

您可以使用以下代码来测试行为

import plac
import time
from itertools import count, izip
import random

#sleep_gen to be defined here

@plac.annotations(
    period=      ("planned period for cycling in seconds (default: %(default)s)", "positional", None, float),
    min_duration=("minimal real 'action' duration in seconds (default:%(default)s)", "positional", None, float),
    max_duration=("maximal 'real action' duration in seconds (default:%(default)s)", "positional", None, float),
)    
def main(period = 1.0, min_duration = 0.1, max_duration = 2.0):
    """Tries to start some randomly long action in regular periods"""
    print """call with -h for help.
    period      : %(period)f
    min_duration: %(min_duration)f
    max_duration: %(max_duration)f""" % locals()
    try:
        last_time = now = time.time()
        header = (   "%5s|"          +"%14s|"    +"%14s|"           +"%8s|"         +"%8s|"          +"%14s|") % ("cycle", "last_time", "now", "action", "real", "next_time")
        row =    "%(i) 5d|%(last_time)14.2f|%(now)14.2f|%(action_dur)8.3f|%(real_dur)8.3f|%(next_time)14.2f|"
        print header
        action_dur = real_dur = 0.0
        for i, next_time in izip(count(), sleep_gen(period)):
            #we care about starting the action on time, not ending
            now = time.time() #sleep_gen just tried to keep the period on schedule
            real_dur = now - last_time
            print row % locals()
            last_time = now
            #performing the "action"
            action_dur = random.random() * (max_duration - min_duration) + min_duration
            time.sleep(action_dur)
    except KeyboardInterrupt:
        print "...cancelled."

if __name__ == "__main__":
    plac.call(main)

从命令行调用它:

$ python cycle.py
call with -h for help.
    period      : 1.000000
    min_duration: 0.100000
    max_duration: 2.000000
cycle|     last_time|           now|  action|    real|     next_time|
    0| 1337368558.55| 1337368558.55|   0.000|   0.002| 1337368559.55|
    1| 1337368558.55| 1337368559.59|   1.042|   1.042| 1337368560.59|
    2| 1337368559.59| 1337368561.32|   1.722|   1.723| 1337368562.32|
    3| 1337368561.32| 1337368562.32|   0.686|   1.000| 1337368563.32|
    4| 1337368562.32| 1337368563.32|   0.592|   1.000| 1337368564.32|
    5| 1337368563.32| 1337368564.75|   1.439|   1.439| 1337368565.75|
    6| 1337368564.75| 1337368566.08|   1.323|   1.323| 1337368567.08|
    7| 1337368566.08| 1337368567.08|   0.494|   0.999| 1337368568.08|
    8| 1337368567.08| 1337368568.20|   1.120|   1.121| 1337368569.20|
    9| 1337368568.20| 1337368569.20|   0.572|   1.000| 1337368570.20|
   10| 1337368569.20| 1337368570.20|   0.586|   1.000| 1337368571.20|
   11| 1337368570.20| 1337368571.20|   0.309|   0.999| 1337368572.20|
   12| 1337368571.20| 1337368572.20|   0.290|   1.000| 1337368573.20|
   13| 1337368572.20| 1337368573.25|   1.052|   1.053| 1337368574.25|
   14| 1337368573.25| 1337368574.25|   0.737|   1.000| 1337368575.25|
   15| 1337368574.25| 1337368575.83|   1.579|   1.579| 1337368576.83|
...cancelled.

将您的问题与我的答案进行比较:

  • generator:是的,它是
  • 输入开始时间:我只使用当前时刻 (可能是人们经常需要的东西)
  • 输入结束时间:此时停止调用生成器。或者修改生成器以仅循环一些循环或在特定时间结束。