-
-
Notifications
You must be signed in to change notification settings - Fork 807
Prefer functions over methods. #244
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
97a79d4 to
bf019cc
Compare
|
+1 (at least)
|
|
Looks good to me, but which is the reason to prefer functions over methods? I always thought methods would be easier to understand and that some Python traits, such as the (I'm not opposing the change, just want to learn more. Maybe a short paragraph discussing both approaches could be added to the instructor's guide) |
|
Poll the 'discuss' list?
|
|
On Wed, Mar 09, 2016 at 01:08:30PM -0800, Ivan Gonzalez wrote:
I remember previous discussion (in the unittest context?) where If there is a functions vs. methods debate, I'd be very careful to |
|
+1 because there is always a function and only sometimes a method. When learners are first learning to code, having to think about whether median has method form or just a function form is extra work that they don't need to do. |
|
My reason for the change is more empirical in that I have had several experiences with learners who use Numpy functions when methods exist (these learners also intuited the I'll send a quick message to the discuss list. |
|
I might have been the one who brought this up. Here are the arguments in favor I can recall:
The argument in favor of methods that I can recall:
|
|
I am in favor of using functions whenever possible for an introduction to Python. In my opinion, the functional style seems to make sense at the low level, while object orientation can be useful in the large. However: If we're also introducing Pandas, methods are very relevant. Idiomatic use of pandas composes methods, so it's some weird middle ground between functional and object-oriented. |
|
👍 functions have to be introduced, objects and methods one can mostly do without. If one strays from Python canon, one can even do without Python built-in methods: >>> x = [3, 1, 2, 0]
>>> list.sort(x)
>>> x
[0, 1, 2, 3]
>>> list.index(x, 2)
2
>>> str.startswith('function', 'fun')
TrueNumPy array functions have the further benefit over methods that they work on any array-like, e.g. >>> import numpy as np
>>> np.mean([0, 1, 2])
1.0 |
|
Not picking a side, just a couple of comments:
|
|
+1 for using functions. At workshops, I've found myself doing a long aside about what methods are, how they're tied to the "type" of object, how to get documentation on them, etc., I know the novice material is designed for first-time programmers, but in practice, learners have programmed in some language before, and the concept of a function is familiar to them. |
|
Note to self: once consensus is reached, add a note to the FAI with a link to this discussion. |
|
I disagree with the consensus here - I think if the goal is to get people up and running in Python, they should have at least seen methods in the class. Object Orientation is of course too much to completely introduce, but if someone takes the workshop and then she tries to use or modify another users code, almost immediately she will encounter a method and be flummoxed. It is worthwhile keeping at least a couple, and saying a short "methods are functions specific to a certain data type" (the blender/light switch example above is great), so that the learner can at least understand what is going on. |
|
I'm also in favour of keeping objects / methods. From my personal experience, having the option of "going object oriented" is one of the biggest advantages of Python over other scripting languages -- I have numerous pieces of work that started as a few quick lines and then evolved into something comprised of a few classes. Also, libraries such as BioPython require some familiarity with classes / instances / methods (and incidentally, the "BioPython Cookbook" does quite a decent job of introducing these without incurring much overhead, see e.g. [1]). Another context where objects are much preferred is random number generation, it would be very unfortunate to lead learners into preferring [1] http://biopython.org/DIST/docs/tutorial/Tutorial.html#htoc16 |
|
On Mon, Mar 14, 2016 at 10:12:37AM -0700, Jan T. Kim wrote:
There's an earlier method reference here 1, but: In addition to having an alphabet, the Seq object differs from the doesn't seem like much of an introduction to methods (i.e. folks who
I think everyone here will agree that methods are a wonderful thing And following up on my earlier commitment 2, previous discussion for |
|
@tbekolay I believe in the Novice Python lesson that covering functions is more important than methods of a class because 1) an understanding of functions is needed to grasp methods; 2) novices are learning quite a bit at once - the additional syntax with methods is not worth the cognitive load; 3) functions are relevant whether doing procedural, object oriented, or functional programming. I like this snippet from Allen Downey's book, Think Like a CS in Python which is open sourced on his website:
|
|
Another comment why I personally prefer to use functions follows from the anti-symmetry of procedural vs. object oriented code as explained in Clean Code, Chapter 6. To quote the bottom line:
I usually want to add new functions which process the data in a new way, but seldom want to add a new type of NumPy array. Thus, it is more natural for me to stick to functions in general. (Though, this does not imply that is easier for a novice.) |
|
@willingc The notion of a "purely mechanical" transformation from functions to methods applies only where methods don't change instance state (see my I'm also not sure about the assumptions about novices: To a total novice, functions and methods will be equally new. To not-quite-novices (as mentioned by @shwina above), one of the variants will appear more familiar / intuitive. I think, though, that the function / method decision should also be based on the effect that may have on learners in the future, as well as factoring in their previous knowledge and "intuition". From that perspective, the group that gets a net benefit from prefering functions is comprised of those who have some previous experience with imperative / procedural programming and who will only do scientific computing of the number crunching type. Those with a different previous background will experience no benefit, and those with tasks that require managing state will miss a key tool that can spare them cartloads of pain. Therefore, even though there's no time in workshops to cover OO completely, I think the use of methods in the Python lesson is quite consistent with the SWC notion of giving learners a good basis to start developing themselves from. |
|
I'm really enjoying this discussion - it's drawing out exactly the kind
of pedagogical content knowledge and personal experience that we all
rely on but rarely articulate. Thank you all...
|
|
On Mon, Mar 14, 2016 at 12:05:05PM -0700, Jan T. Kim wrote:
But it's not a function vs. methods decision, is it? It's a functions |
|
I'm not sure if this should be part of the discussion here, but using methods has also the additional disadvantage that finding help on them is actually quite non trivial. For the numpy |
|
All the the points above (both for and against) have been very interesting. Consider an operation like Root Mean Squared. Using functions or the code is very similar to the operation's English name (RMS), and the code can be read from left to right. is both less readable as doesn't work, as neither or both work, but in my opinion are less readable and more complex, due to chaining a method to a statement in parentheses. I believe that this example, and others that come to mind (Sum Squared Error), functions produce clearer code. Can someone think of a nice counter-example? |
|
On Mon, Mar 14, 2016 at 01:22:59PM -0700, Kyler Brown wrote:
I'm sure both have situations where they are more appropriate. For Still, this is all in the “for idomatic Python use” level, when the Getting a better handle on the bumped information would help nail this |
|
+1 to this PR and +1 to the discussion of it. Related to SWC material, I'd like to say that this discussion also emphasizes how much development pressure our community is under to provide intermediate material, e.g. in python. This would be a perfect place to discuss "functions vs methods", to teach unit tests (including pulling them out of novice-python) as recently discussed on the mailing list, etc. As Greg once said, coming up with teaching material is about deciding what is essential and what is important. this PR is a prime example for this. |
|
This discussion reminds me of the old Numeric manual that I read a long time ago before numpy was universal and we still had to deal with Numeric and numarray: quoting http://numpy.sourceforge.net/numdoc/numdoc.pdf
|
|
Revisiting this after sleeping on it I still object to the addition of and avoid all that state management mess and nonsense. If as a novice I had seen an example of random number generator objects, even without much elaboration, that might well have saved me that month of messing and worrying, and therefore I argue for using objects rather than functions in any context of random numbers so SWC novices may be spared from that waste of time. In general OO terms, this is an example of encapsulation. With respect to the extent to which OO is covered in SWC, I suggest that learning to use encapsulated objects should be a novice learning objective (it's not really possible to use Python without using objects anyway), while writing classes could be considered intermediate material. [1] bf019cc#diff-150012b0321d07fbe188f0c1a85c9c7eL408 |
|
Strings are one place that "methods" could be introduced to students. Strings are something that folks tend to understand fairly simply. In Python, Strings (str objects) and the associated string methods are well encapsulated and understandable for a novice. Using Strings as the foundation for learning methods would be more effective than combining methods and functions when teaching the numpy array examples. |
|
On Tue, Mar 15, 2016 at 05:26:19AM -0700, Jan T. Kim wrote:
How about replacing that with time.time()? |
|
@willingc good idea to use simple built-in types. Some methods already appear in the lists section, so there may be opportunity to focus on them a bit more and then use string methods to reinforce them? Some list methods are also quite simple: Perhaps something along these lines could be added to 03-lists.md? |
|
On Tue, Mar 15, 2016 at 10:34:35AM -0700, Jan T. Kim wrote:
Ah, good point. If the goal is to remove method references, odds = list(reversed(odds)) or: odds = odds[::-1] which are different (creating a new object) than odds.reverese()
and while generators are lovely, efficient things, I think we should There's also odds.append(11) 2, which would have to be replaced by: odds = odds + [11] which also creates a new object. And in both cases, the method There's a lot of material in this lesson, and we could probably just |
|
@wking regarding |
|
@wking I didn't mean to suggest replacing list methods with functions. I think it's important to learn about basic operations on mutable objects, especially the |
|
On Tue, Mar 15, 2016 at 10:54:30AM -0700, Jan T. Kim wrote:
Time is something everyone is familiar with, and the callout is just |
|
On Tue, Mar 15, 2016 at 11:02:28AM -0700, Jan T. Kim wrote:
Right, I'm just saying that if avoiding methods is a pedagogical goal
There's a lot of mutable discussion in a call out in 03-lists, and you
I agree (see my “bigger reduction” comment in 2). And maybe
Right, which is why I prefer the [::-1] slice, although it looks like |
|
@wking one thing that you mentioned may be quite important in this thread. image = matplotlib.pyplot.imshow(data)
matplotlib.pyplot.show()The lack of parameters for show() is the less troublesome aspect. We have imshow taking an argument, returning something, but neither are used in show(). imshow is changing the internal state of pyplot, then at this point the different between function and methods and the implications of side-effects should be mentioned, no matter if everything else was switched to functions. |
|
On Tue, Mar 15, 2016 at 11:47:53AM -0700, Giuseppe Profiti wrote:
Good point. This is another instance of matplotlib's global state It's frustrating to be one matplotlib.pyplot.show(image) away from |
|
I thought about this for a while and I agree with this as a general rule. Avoiding odd syntax, that simplifies things when you are hacking between scopes that you probably shouldn't, is a good idea for beginners. |
|
I think that methods (as we currently teach them in the lesson) don't add much extra load and I'd prefer them for the simplicity in the code. It's a big effort for the learners to follow the lesson and type, so if we can save them 10-20% of the typing by using methods, I'd go for it. I think that methods are a natural follow up from objects and, conceptually, don't differ much from attributes, which we need to explain anyways. I introduce objects very early, actually in the line that creates the first "variable". I mention "variable", but prefer to talk about names and objects, rather than variables and values. I think this is much aligned with the realities of both Python and the audience, e.g. people not coming from the hard sciences may not be used to think in terms "variables" having "values". The great thing about objects is that the technical concept fits very well with many learner preconceptions: "everything is an object", "objects are physical things that take space somewhere", "objects have names", "the same object can have several names", "an object without a name cannot be found", "objects can be grouped in classes", "objects can be made up of other objects", ... (I'm not going into differences between objects, instances, classes and all that...) From there to "objects can have actions associated to them" is a short step in my opinion: at the end, most of our day is spent dealing with interfaces to act on human-made objects. The ubiquitous On the other hand, I've never tried the function approach, so this is just an opinion. Maybe we should start "A/B testing" these things. Given that we are teaching almost a workshop a day and the alternative version in this PR is ready, it would take just a few of weeks to collect enough data to have a better answer to this. |
|
Hi all, I changed the Since discussion seems to be winding down, I've compiled a summary of the arguments made in this thread so far; please feel free to correct me if I've misconstrued anything! I didn't notice any obvious groupings other than arguments specific to NumPy and general arguments for or against teaching methods. Arguments in favor of switching methods to functionsGeneral:
NumPy specific:
General +1s not cited above: @jiffyclub, @douglatornell, @gdevenyi, @fu9ar Arguments in favor of keeping methods
Compromises / caveats
Published quotes of interest
From Think like a computer scientist in Python by Allen Downey
From Clean Code by Robert C. Martin
From Numeric manual SummaryIn all, I read:
To me, this summary means that we should merge this PR. I believe that adding extra explanation about methods in the string / list sections, or removing the use of methods in these sections should be left to another issue / PR if anyone feels strongly about these changes. @abostroem, if you agree with the assessment, then I'll leave the merging up to you! @gvwilson Is a summary of this thread worth a blog post? |
|
On Sat, Mar 26, 2016 at 11:37:19AM -0700, Trevor Bekolay wrote:
It's nice to see everything laid out so compactly :). |
|
Thanks, @tbekolay: I vote to make it into a blog post :) |
|
+1 |
Most methods on NumPy arrays also have an equivalent NumPy functions that takes the array as input. I have noticed that many novice programmers prefer function (which have a pretty clear input-output relationship) to methods (which have an implicit input). This commit changes all instances of calling methods on arrays to calling the equivalent NumPy function instead. I tried to simplify the explanation in `01-numpy.md` as well, which hopefully does not significantly affect the flow of the prose. I also added a "function" entry to the glossary and linked to it in `01-numpy.md`.
5e7e45f to
81a3560
Compare
|
I rebased and merged this as per the discussion. I'll write the corresponding blog post shortly! |
Most methods on NumPy arrays also have an equivalent NumPy function that takes the array as input. I have noticed that many novice programmers prefer functions (which have a pretty clear input-output relationship) to methods (which have an implicit input). This PR changes all instances of calling methods on arrays to calling the equivalent NumPy function instead. I tried to simplify the explanation in
01-numpy.mdas well, which hopefully does not significantly affect the flow of the prose.This PR came out of one of the discussion sessions (apologies, I don't remember who brought this up -- if it was you, let me know and I'll add you to the commit message :) )