Looping over list of dicts returns last element n times

Viewed 36

I'm facing a pretty random problem in Python (3.10.7) right now: I have a list of dictionaries that I want to convert into a list of Python objects. Using list comprehension or a basic for-loop, I expect to create a new list of objects - one for each element in the list of dicts.

This is the list of dicts I receive:

events = [
    {
        "event_key": "test.test.test_one",
        "timestamp": "2022-01-01T01:01:00"
    },
    {
        "event_key": "test.test.test_two",
        "timestamp": "2022-01-01T02:02:00"
    }
]

And this is the list I would expect:

[
    Event(key="test.test.test_one", timestamp="2022-01-01T01:01:00"),
    Event(key="test.test.test_two", timestamp="2022-01-01T02:02:00"),
]

But what I get is this:

[
    Event(key="test.test.test_two", timestamp="2022-01-01T02:02:00"),
    Event(key="test.test.test_two", timestamp="2022-01-01T02:02:00"),
]

To convert the list of dicts, I use list comprehension as follows:

events_list = [Event(event["event_key"], event["timestamp"]) for event in events]

I also tried the most basic way using this code:

events_list = []
for event in events:
    key = event["event_key"]
    timestamp = event["timestamp"]
    event = Event(key=key, timestamp=timestamp)
    events_list.append(event)

Inserting a print statement for the attributes or class during the for-loop shows me that the loop and mapping work correctly, but once the item is appended to the list it seems like the new value overwrites the existing ones + appends the new item at the end.

As asked in the comments, here is the custom class as well as the value objects:

class EventKey:
    key_pattern = re.compile(r"^([a-z_]+\.){2,}[a-z_]+$")

    def __get__(self, obj, objType=None):
        return self.value

    def __set__(self, obj, value):
        if not isinstance(value, str):
            raise TypeError("Event key must be a string")

        if not self.key_pattern.match(value):
            raise ValueError("Event key is not a valid format")

        self.value = value


class EventTimestamp:
    pattern = re.compile(r"^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}([Z]|)$")

    def __get__(self, obj, objType=None):
        return self.value

    def __set__(self, obj, value):
        if not isinstance(value, str):
            raise TypeError("Event timestamp must be a string")

        if not self.pattern.match(value):
            raise ValueError("Event timestamp is not a valid format")

        try:
            datetime.datetime.fromisoformat(value.replace("Z", "+00:00"))
        except ValueError:
            raise ValueError("Event timestamp is not a valid format")

        self.value = value


class Event:
    key: EventKey = EventKey()
    timestamp: EventTimestamp = EventTimestamp()

    def __init__(self, key: EventKey, timestamp: EventTimestamp):
        self.timestamp = timestamp
        self.key = key
    
    def to_dict(self):
        return {"event_key": self.key, "timestamp": self.timestamp}

Help is very much appreciated as this issue is slowly driving me crazy.

0 Answers
Related