在Python中的__init__中使用* args和** kwargs的SyntaxError

SyntaxError using *args and **kwargs in an __init__ in Python

我试图定义一个类RecurringInterval,它通过组合使用dateutil.rrule中的rrule类,另外还有一个属性period,默认为None。我试图用这种方式初始化它:

1
2
3
4
5
6
class RecurringInterval(object):
    def __init__(self, *args, period=None, **kwargs):
        self.period = period
        self.rrule = dateutil.rrule.rrule(*args, **kwargs)

recurring_interval = RecurringInterval(dateutil.rrule.DAILY, count=1)

但是,我得到了一个SyntaxError

1
2
3
4
  File"/home/kurt/dev/scratch/Furion_scheduler/recurring_interval.py", line 7
    def __init__(self, *args, period=None, **kwargs):
                                   ^
SyntaxError: invalid syntax

据我所知,位置参数应该在关键字参数之前,所以这是我期望的语法;我将如何更正它?(从https://docs.python.org/2/tutorial/controlflow.html解包参数列表中,我还不清楚这一点)。

我试着把period=None带到前面,就像这样:

1
2
3
4
class RecurringInterval(object):
    def __init__(self, period=None, *args, **kwargs):
        self.period = period
        self.rrule = dateutil.rrule.rrule(*args, **kwargs)

但这就产生了一个TypeError

1
2
3
4
5
6
Traceback (most recent call last):
  File"/home/kurt/dev/scratch/Furion_scheduler/recurring_interval.py", line 9, in <module>
    recurring_interval = RecurringInterval(dateutil.rrule.DAILY, count=1)
  File"/home/kurt/dev/scratch/Furion_scheduler/recurring_interval.py", line 7, in __init__
    self.rrule = dateutil.rrule.rrule(*args, **kwargs)
TypeError: __init__() takes at least 2 arguments (2 given)

如何以预期的方式初始化RecurringInterval


应该是:

1
def __init__(self, period=None, *args, **kwargs):


更新答案

在python之后,在可变长度位置参数之后的默认关键字参数,下面在python 3中工作:

1
2
3
4
class RecurringInterval(object):
    def __init__(self, *args, duration=datetime.timedelta(seconds=0), **kwargs):    # Initializing in this way only works in Python 3
        self.duration = duration
        self.rrule = dateutil.rrule.rrule(*args, **kwargs)

旧答案

在这篇Github文章之后,我找到了一个使用kwargs.pop的解决方案:

1
2
3
4
5
6
class RecurringInterval(object):
    def __init__(self, *args, **kwargs):
        self.period = kwargs.pop('period', None)
        self.rrule = dateutil.rrule.rrule(*args, **kwargs)

recurring_interval = RecurringInterval(dateutil.rrule.DAILY, count=1, period=datetime.timedelta(days=2))

这样,period作为关键字参数给出,分配给self.period,默认值为None,其余的argskwargs用于初始化RecurringIntervalself.rrule