-2

I have defined a class which uses a constructor that's meant to allow any number of a set of properties be attributed:

class CalendarEvent:
    """Represents a macOS calendar event."""
    def __init__(self, **keyword_arguments):
        self.__allowed_properties = ["starts", "ends", "repeat", "end_repeat", "travel_time", "alert", "notes", "invitees"]
        for key, value in keyword_arguments:
            if key in self.__allowed_properties:
                setattr(self, key, value)

When I try to create a CalendarEvent though,

party_tomorrow = CalendarEvent(
        starts = datetime.datetime.today() + datetime.timedelta(days = 1),
        ends = datetime.datetime.today() + datetime.timedelta(days = 1, hours = 5),
        repeat = None, 
        end_repeat = None,
        travel_time = datetime.timedelta(hours = 1),
        alert = None,
        notes = "This is gonna be a load of fun.",
        invitees = None
        )

I get the error:

Traceback (most recent call last):
  File "/Users/George/Library/FlashlightPlugins/calendarquery.bundle/plugin.py", line 62, in test_CalendarEvent
    invitees = None
  File "/Users/George/Library/FlashlightPlugins/calendarquery.bundle/plugin.py", line 12, in __init__
    for key, value in keyword_arguments:
ValueError: too many values to unpack (expected 2)
theonlygusti
  • 11,032
  • 11
  • 64
  • 119
  • Instead of `self.__allowed_properties =`, I suggest just having `__allowed_properties` outside any method as a class attribute. – Alex Hall Dec 26 '16 at 11:42
  • @AlexHall ok, I am still getting used to python. Thanks ;) – theonlygusti Dec 26 '16 at 11:43
  • One problem with this method is that those properties have no default values, so if you forget to set one of them and try to access it later you'll have a nasty error. – Alex Hall Dec 26 '16 at 11:43
  • @AlexHall is there no way to check whether it exists or not? My plan was to later do something like `event.alert is not None`? I am going to put this onto codereview.SE though, I really need to learn how to Python. – theonlygusti Dec 26 '16 at 11:45
  • Checking like that won't work. You could use `getattr` with a default or `hasattr`, but it would be much nicer for your code in general to have a default set at the beginning, and presumably some of these have sensible defaults other than `None`. – Alex Hall Dec 26 '16 at 11:47
  • Hmm ok. Thanks for all your help! That makes a lot of sense, I think I'm gonna brush up my code now... – theonlygusti Dec 26 '16 at 11:50

1 Answers1

2

Simply iterating over a dictionary directly only iterates over its keys. You want:

    for key, value in keyword_arguments.items():
Alex Hall
  • 34,833
  • 5
  • 57
  • 89