1

I'm trying to define a class RecurringInterval which uses the rrule class from dateutil.rrule through composition, and in addition has the attribute period which by default is None. I've tried to initialize it in this way:

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)

However, I get a SyntaxError:

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

As I understand it, positional arguments should come before keyword arguments, so this is how I would expect the syntax to be; how would I correct it? (From https://docs.python.org/2/tutorial/controlflow.html#unpacking-argument-lists this is not yet clear to me).

I tried bringing period=None forward, like so:

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

but this gives rise to a TypeError:

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)

How can I initialize the RecurringInterval in the intended fashion?

Kurt Peek
  • 52,165
  • 91
  • 301
  • 526
  • Are you using Python 2 or Python 3? I think you can definitely do what you're trying to do there in python 3, but might not be possible in 2. The docs you're referring to are covering function calling rather than function definition. – Hammerite Nov 23 '16 at 16:36
  • 1
    [Hammerite](http://stackoverflow.com/users/340819/hammerite), I'm using Python 2. With the `__init__` as `__init__(self, period=None, *args, **kwargs)`, I tried running the code in Python 3, but I then get `TypeError: __init__() missing 1 required positional argument: 'freq'`. – Kurt Peek Nov 23 '16 at 16:46

2 Answers2

4

It should be:

def __init__(self, period=None, *args, **kwargs):
Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895
  • Daniel, I tried this, but it leads to a `TypeError` rather than a `SyntaxError` (see the latter part of the question). How would I 'totally' fix the code? – Kurt Peek Nov 23 '16 at 16:43
  • @KurtPeek that's another different error than your question – MooingRawr Nov 23 '16 at 16:50
1

Updated answer

Following Python, default keyword arguments after variable length positional arguments, the following works in Python 3:

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)

Old answer

Following this Github article, I found a solution using kwargs.pop:

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))

This way, period is given as a keyword argument, it is assigned to self.period, the default value of which is None, while the remaining args and kwargs are used to initialize the RecurringInterval's self.rrule.

Community
  • 1
  • 1
Kurt Peek
  • 52,165
  • 91
  • 301
  • 526