G-XR8P2XJ088

AI-Written Python: Give Each Workshop Its Own List

A workshop organiser asks an AI assistant to prepare two booking lists, one for the morning session and one for the afternoon. The generated script prints a dictionary with both session names, each followed by an empty list. Everything looks right. Then the organiser adds booking B17 to the morning. The afternoon list now contains B17 too, although no one added it there.

This is a fictional example, but the Python behaviour is real. The script made two dictionary entries and gave them the same list. Each name provides a way to reach that list. If you only check the starting display, the two empty brackets can look like independent containers. You find out what was built when you change one of them.

Read what the constructor promises

The Python documentation for dict.fromkeys() says it creates a dictionary whose keys come from the supplied collection. Each key gets a reference to the same supplied value. In the example below, Python evaluates [] once when preparing the call. The method then uses that one list for both keys. The dictionary itself is new; its values are shared.

sessions = ("morning", "afternoon")
bookings = dict.fromkeys(sessions, [])
bookings["morning"].append("B17")

assert bookings["afternoon"] == ["B17"]
assert bookings["morning"] is bookings["afternoon"]

The last check uses is to ask whether both lookups return the very same object. The other check asks what the afternoon list contains. For the organiser, that second question is the important one: a morning booking must not appear on the afternoon register. The identity check explains the cause, while the contents check shows why the cause matters.

There are sensible uses for a shared starting value. If each session begins with the status None and the script later assigns a new status to one key, the other key stays as it was. An assignment such as bookings["morning"] = ["B17"] would also replace only the value at that key. It is the in-place change to a shared list, such as append(), that shows up through every key still pointing to it.

Create a list inside each iteration

A dictionary comprehension builds the keys and values together. The Python language reference describes how it produces a key and value for each iteration. Put [] inside that expression and Python creates a fresh empty list each time. The session names are unchanged; the lists now belong to their respective entries.

bookings = {session: [] for session in sessions}
bookings["morning"].append("B17")

assert bookings["morning"] == ["B17"]
assert bookings["afternoon"] == []
assert bookings["morning"] is not bookings["afternoon"]

A comprehension can still share a value if you write {session: template for session in sessions} and template is one list created earlier. Check where the list comes into existence. If every session should begin with an editable checklist, create a fresh checklist for each one. If its items are themselves editable objects, check those too. The related MaryChuks guide on shared records inside a copied list explains why making a new outer list may leave its inner records shared.

Test the boundary using the way people really work

The booking example keeps the first test small on purpose. Add a booking to one session and inspect the other. A larger test where both sessions receive the same booking by design would miss the problem. Pick values that should be different, and write down the expected results before you run the script.

  • Change just one group. Add a booking to the morning session and check that the afternoon remains empty. Then add a different booking to the afternoon and check the morning again.
  • Try the real edit. If staff cancel bookings or change their status, include that operation. A workflow that replaces whole lists in one test may still share a list that staff edit in place.
  • Check what gets handed over. If the script exports a register for each tutor, open both files and check that B17 appears only on the expected one. Distinct lists in memory do not prove the export uses the right entry.

A bug like this can also disguise itself as a business discrepancy. If the afternoon register includes an unfamiliar booking, compare it with the source booking record before removing it from the list. Deleting the unexpected item from a shared list could also remove it from the correct session. Fix the way the lists are created, then rebuild the registers from the source so you can tell what belongs where.

Include an empty session in the test. A register that contains the right booking for every populated group can still conceal a problem if your export never shows empty groups. Keeping an empty session visible helps you check both that the group was created and that it stayed independent.

Put independence in the brief

If an assistant is writing the script, ask for the behaviour you need: ‘Create a separate editable list for every session. Add a morning booking and demonstrate that the afternoon list is unchanged. Then add an afternoon booking and check both outputs.’ The instruction gives the assistant a condition to meet and gives you a check you can run without knowing the implementation in advance.

The same test is useful for customer groups, folders of review notes and per-project task lists. Wherever two names are meant to keep their own records, make one change and look at the other. That is the difference between seeing two empty lists in a printout and knowing each group can be edited on its own.

Sources


Discover more from Marychuks.com AI, Psychology, Business & CreativeVerse

Subscribe to get the latest posts sent to your email.

Leave a Reply

Discover more from Marychuks.com AI, Psychology, Business & CreativeVerse

Subscribe now to keep reading and get access to the full archive.

Continue reading