Python List Methods Clarity

In list_methods.py, the tests check that the list in the parameter has been modified correctly and that the returned list is correct. So, the following is a correct solution:

def remove_the_mean_person(queue, person_name):
    queue.remove(person_name)
    return queue

This seems redundant, as the list queue is mutable, and a return statement here is unnecessary. The same list is being asserted twice.

However, this code is not accepted:

def remove_the_mean_person(queue, person_name):
    return [p for p in queue if p != person_name]

It correctly returns a list, but does not mutate the queue parameter.

The exercise instructions do not clearly indicate why the latter code isn’t a correct solution. I had to carefully inspect the exceptions to understand.

I would expect a function to either modify the parameter and return nothing or return a modified list. I wouldn’t expect both. The tests in list_methods.py require both, making for awkward (in my opinion) solutions. However, I’m relatively new to Python, and this may be a common pattern.

Welcome to test driven development ;) Reading and understanding the exceptions is explicitly something you are expected to do.

You’re correct that functions in general do one or the other but not both. Most of the built-in functions that modify a collection return None.

Also worth reading is Suggesting Exercise Improvements | Exercism's Docs

I’ve practiced and taught TDD for 20 years, I understand :grinning:

To that, though, the level of Python required for these exercises’ tests and exceptions to be comprehensible to a learner is significantly higher than the level of Python needed for the exercises themselves. This mismatch would lead me to consider more explicit English specifications.

I’m not a Python expert, so I’m trying not to be strongly opinionated here. However, I’ve never seen this mutate and return pattern used in any other language. I prefer the return coming from FP, but whatever is Pythonic is fine with me! Since it is unusual in Python as well, perhaps the exercises shouldn’t adopt it for the sake of testing at the risk of teaching anti-patterns.

I will follow the second link! I wanted to start a discussion with folks who know more about Python than I do before suggesting changes to the repositories.

Hi :wave: Python maintainer here. :slightly_smiling_face:

Welcome to the Exercism forums!

While Isaac is correct that we expect students to read and understand the tests and exceptions for practice exercises, we do NOT expect students to do so for concept exercises. In fact, we hide the tests for concept exercises in the UI.

Chaitanas Colossal Coaster is a concept exercise covering list methods. The requirements for concept exercises (see also these details) are different from those of the practice exercises.

Before I go on in detail, I’d like to say that this exercise has been worked over quite a bit due to mutability debates (here is one discussion, but there are more). It perhaps needs to be replaced or redone — either back to being agnostic about mutability, or explicit/ prescriptive about making copies for return everywhere. I’d welcome suggestions to that end, provided it doesn’t overload this exercise.




Significantly, concept exercises are not supposed to introduce concepts beyond what has been covered up to that point in the Syllabus, and should contain all the data needed to pass the tests - and no more.

list-methods as a concept comes in around the 5th or 6th lesson. Before we’ve had a chance to cover None, call-by-object-reference (see this and this if you want details on pitfalls), classes, or other more complex topics like mutability, first-class-objects, and more-on-functions.

We could add a note about the convention - either in the instructions or the introduction. But I am not at all sure that wouldn’t lead to further questions and confusion. It is also a convention. It is not mentioned in the docs on functions, in PEP8, nor is it a Pylint rule. And there are exceptions (list.pop being one) in both the std lib and 3-party libraries. There is a note under list.sort — mostly to steer folx away from what a foot-gun it is.

As mentioned in the forum discussion I referenced above, the intent of this exercise was to have students practice the list-methods, and (perhaps) learn a few lessons about the potential pitfalls of mutable data structures. So going into None, copy(), the presence or lack of return in a function, etc was out of scope. And as the Syllabus docs say:

Often the earliest exercises need to contain non-idiomatic code. This is because in the beginning most of the language is still unknown to the student, and most of the concepts have not yet been introduced. By allowing non-idiomatic code in the earliest exercises, students are able to take many smaller steps in familiar territory rather than a few big steps in unfamiliar territory. The result is that they are able to reach the stage of idiomatic code more quickly and with less friction.

But again - perhaps we need to just nuke this exercise and start over - or re-work it to be very very explicit. :slightly_smiling_face: Suggestions welcome.

(thank you for reading this far…)

2 Likes