如何创建月迭代器

dge*_*gel 22 python

我想创建一个python函数,允许我迭代从起点到停止点的几个月.例如,它看起来像

def months(start_month, start_year, end_month, end_year):
Run Code Online (Sandbox Code Playgroud)

呼叫months(8, 2010, 3, 2011)将返回:

((8, 2010), (9, 2010), (10, 2010), (11, 2010), (12, 2010), (1, 2011), (2, 2011), (3, 2011))
Run Code Online (Sandbox Code Playgroud)

该函数可以返回一个元组元组,但我希望将其视为生成器(即使用yield).

我检查了calendarpython模块,它似乎没有提供此功能.我可以写一个令人讨厌的for循环来轻松地完成它,但我很想知道专业人员可以做得多么优雅.

谢谢.

S.L*_*ott 43

日历的工作方式如下.

def month_year_iter( start_month, start_year, end_month, end_year ):
    ym_start= 12*start_year + start_month - 1
    ym_end= 12*end_year + end_month - 1
    for ym in range( ym_start, ym_end ):
        y, m = divmod( ym, 12 )
        yield y, m+1
Run Code Online (Sandbox Code Playgroud)

所有多单元的东西都是这样的.英尺和英寸,小时,分钟和秒等等.唯一不那么简单的事情是数月或数月 - 因为月份是不规则的.其他一切都是常规的,你需要在最细粒度的单位工作.


eto*_*ipi 10

由于其他人已经提供了生成器的代码,我想补充一下 Pandas 有一个名为“ period_range ”的方法,在这种情况下,它可以接收开始和结束、年和月,并返回一个周期索引,适合迭代。

import pandas as pd

pr = pd.period_range(start='2010-08',end='2011-03', freq='M')

prTupes=tuple([(period.month,period.year) for period in pr])

#This returns: ((8, 2010), (9, 2010), (10, 2010), (11, 2010), (12, 2010), (1, 2011), (2, 2011), (3, 2011))
Run Code Online (Sandbox Code Playgroud)


k10*_*107 6

months使用dateutil模块功能

from dateutil.rrule import rrule, MONTHLY
from datetime import datetime

def months(start_month, start_year, end_month, end_year):
    start = datetime(start_year, start_month, 1)
    end = datetime(end_year, end_month, 1)
    return [(d.month, d.year) for d in rrule(MONTHLY, dtstart=start, until=end)]
Run Code Online (Sandbox Code Playgroud)

用法示例

print months(11, 2010, 2, 2011)
#[(11, 2010), (12, 2010), (1, 2011), (2, 2011)]
Run Code Online (Sandbox Code Playgroud)

或以迭代器形式

def month_iter(start_month, start_year, end_month, end_year):
    start = datetime(start_year, start_month, 1)
    end = datetime(end_year, end_month, 1)

    return ((d.month, d.year) for d in rrule(MONTHLY, dtstart=start, until=end))
Run Code Online (Sandbox Code Playgroud)

迭代器用法

for m in month_iter(11, 2010, 2, 2011):
    print m
    #(11, 2010)
    #(12, 2010)
    #(1, 2011)
    #(2, 2011)
Run Code Online (Sandbox Code Playgroud)

  • 请注意,[**`dateutil`**](https://dateutil.readthedocs.org/en/latest/) 是第三方模块。 (2认同)

dfa*_*fan 5

也许这种优雅或速度可以提高,但这是直截了当的解决方案:

def months(start_month, start_year, end_month, end_year):
    month, year = start_month, start_year
    while True:
        yield month, year
        if (month, year) == (end_month, end_year):
            return
        month += 1
        if (month > 12):
            month = 1
            year += 1
Run Code Online (Sandbox Code Playgroud)

编辑:这是一个不太直接的,甚至可以避免yield使用生成器理解需要使用:

def months2(start_month, start_year, end_month, end_year):
    return (((m_y % 12) + 1, m_y / 12) for m_y in
            range(12 * start_year + start_month - 1, 12 * end_year + end_month))
Run Code Online (Sandbox Code Playgroud)