This issue describes how to implement the list methods concept exercise for the Python track, which should familiarize the student with the core list methods.
Please please please read the docs before starting. Posting PRs without reading these docs will be a lot more frustrating for you during the review cycle, and exhaust Exercism's maintainers' time. So, before diving into the implementation, please read up on the following documents:
Please also watch the following video:
This concept exercise should familiarize the student with some of the core list methods that manipulate/mutate lists, and when/how to use them.
list class & its core methodslist to operate on itlist methods _mutate the list_ -- they do not return or make a new list.list methods -- one at least from each grouping below to _mutate_ a list:append()/extend() methodsinsert() methodpop()/remove() methodssort()/reverse() methodslist with the copy() methodlist with the count() methodindex of the element in a list with the index() methodmin(), max(), and len()deque & UserListlist comprehensionsmap() and reduce() for operations on a listlist as an argumentlist with the copy() method vs deep_copy()listbasicsbooleansiteration, iterablesloopsmethodssequencesExplain more about:
methods of list & Pythons built-in methods called with a _list as argument_ (e.g. reversed(), sorted(), len() ...).listsNo changes required.
No changes required.
Tests should be written using unittest.TestCase and the test file named comparisons_test.py.
If you have any questions while implementing the exercise, please post the questions as comments in this issue.
## Edits
-
馃敟 馃敟 馃敟 -- @DavidGerva you are on a roll! Many thanks for this.
@mohanrajanr will be taking this on. YAY.
@DavidGerva @BethanyG : To Test this exercise, I came up with the following plan.
class ListWrapper(list):
def __init__(self, iterable=(), **attr):
super().__init__(iterable=iterable, **attr)
self.execution_history = []
def append(self, value):
self.execution_history.append('append')
super().append(value)
def extend(self, value):
self.execution_history.append('extend')
super().extend(value)
a = ListWrapper()
a.append(1)
a
#=> [1]
a.execution_history
#=> ['append']
This looks like a more plausible way to understand whether the user used the function in the code. All the Test cases will be manipulating the list which we pass ( the list wrappered object is the one we will pass in the test ) and we can test all the list methods :) .
At first i thought whether we can monkey patch built in object or use decorator of some sorts, but listwrapper seemed more easier to do.
Thoughts?.
And Also, I know Jeremy has an Issue raised about differentiating on exercises and concepts. So Should I go on with the PR or should I wait?
This looks like a more plausible way to understand whether the user used the function in the code. All the Test cases will be manipulating the list which we pass ( the list wrappered object is the one we will pass in the test ) and we can test all the list methods :) .
As a _rule_ on exercism, test don't test _implementation_. This has three reasons, if not more:
However, _we have a way_ to guide a student to use specific implementations! We allow analyzers to test implementation. This has a sidenote: we often suggest you only give feedback on proven positives, and not potential positives. What does this mean? Instead of analyzing "uses append", you would instead analyzer "uses for each" and suggest append. This way, when _new ways are added_ in the future, the analyzer doesn't break!
And Also, I know Jeremy has an Issue raised about differentiating on exercises and concepts. So Should I go on with the PR or should I wait?
Just continue. You're doing great, and it's easy for us to "fix" / do another PR to update once that idea lands. No need to wait.
@SleeplessByte : Thanks for your comments.
You probably won't and shouldn't test implementation when writing this code in the wild, you'd test outcome.
Got it!. I think this line resonates better about the thought i should give on writing test cases.
it's easy for us to "fix" / do another PR to update once that idea lands.
Great. I will proceed working with this.
Created a PR for this Issue here : https://github.com/exercism/v3/pull/2303
I missed this issue when it was created. Was there a discussion at some point on naming this concept "list methods" instead of just "list"?
Yeah. That naming struggle (_and grouping of concept and terms_) is ongoing. We already have lists, but purposely limited the coverage of specific methods there.
I am debating if we do an iterables or sequences concept for things like bracket notation, indexing, slicing -- all the common sequence operations that apply across sequence types (_help thinking through that warmly welcomed_).
If we were to do that, then there is this space "in between" the basic data structures (_what they are, if they are mutable, immutable, how to make one, how to update one_) and the more general _types_ and how those get used/interpreted (sequence, mapping, stream, etc.) where there are useful or important methods specific to only that class (str.join(), list.sort(), etc.). We also have a strings and string-methods (and in fact have string formatting). And I am assuming we'd probably have a dict-methods too. But I am not very happy with it - I just don't know yet what a better grouping is.
I'll admit that methods is an overloaded word - but operations (or operating on lists) doesn't really feel correct either. The docs use methods. Not that that recommends the term as a concept:
The list data type has some more methods. Here are all of the methods of list objects
Thoughts? These are things that are important for a student as basic building blocks, and I don't think the list exercise is detailed enough (_nor should it be as a concept exercise_) to then point the student to the List class and say "have at it!".
I'll admit that methods is an overloaded word - but operations (or operating on lists) doesn't really feel correct either. The docs use methods. Not that that recommends the term as a concept:
Not to mention that we also have a list-ops practice exercise...
I do like the idea of an iterables concept. Frequently in Python it doesn't matter what the exact type of a variable is; its behavior (or "group") is usually more important. It feels right to integrate that ideology to our concept exercises too.
Since PR #2303 has been merged 馃帀 , I am closing this issue.