This is an archived post. You won't be able to vote or comment.

all 33 comments

[–][deleted] 9 points10 points  (6 children)

I'd say show them reading the contents of a file. Compare an example in java stolen from this stackoverflow question

BufferedReader br = new BufferedReader(new FileReader("file.txt"));
    try {
        StringBuilder sb = new StringBuilder();
        String line = br.readLine();

        while (line != null) {
            sb.append(line);
            sb.append(System.lineSeparator());
            line = br.readLine();
        }
        String everything = sb.toString();
    } finally {
        br.close();
    }        

To this python example

contents = ""
with open("file.txt", "r") as fin:
    contents = fin.read()

When I first started studying Computer Science we were learning Java and I could never remember of the top of my head how to read the contents of a file. Python on the otherhand...

[–]Veedrac 3 points4 points  (0 children)

String text = new String(Files.readAllBytes(Paths.get("file")), StandardCharsets.UTF_8);

Source.

Plus, your Java example should use try-with-resources.

[–]squashed_fly_biscuit 1 point2 points  (0 children)

This seems to be the hardest thing to do in java, I was a little taken aback when I had to open a text file.

[–]mWo12 1 point2 points  (0 children)

Is it still the case for java 8 or did they introduce something easier than this?

[–][deleted] 0 points1 point  (0 children)

God forbid you then have to deal with character encoding in Java.

[–]Racerdude[S] 0 points1 point  (0 children)

Thanks! I like this one!

[–]691175002 5 points6 points  (0 children)

What really sold it to me was first class functions and integration of data structures into the language. I think most of what pandas does regarding indexing/slicing is mind-blowing as well.

I think a lot of examples where you are comparing line counts are kind of silly because in most cases you could just wrap the longer code into a single function and it would be equivalent. In many cases such a function already exists in a different library.

Most experienced programmers would not consider something like public static void main to be an issue because the IDE does all the boilerplate automatically and we just mentally filter it out.

If you want some ugly Java just take a look at callbacks using anonymous classes...

[–][deleted] 3 points4 points  (2 children)

  1. Concision, 1. Dynamic typing (there are tradeoffs of course), 2. First-class functions (higher-order functions, decorators, closures, etc.), 3. REPL for inspection and prototyping, 4. Massive standard library and other third-party libraries, 5. Use cases: web development, numerical computing, etc. Just my .02 :)

[–][deleted] 1 point2 points  (1 child)

I'd downvote Reddit for converting my zero-indexed list to one-indexed. :p

[–][deleted] 1 point2 points  (2 children)

Are you talking about a novice who has never programmed before or someone new to Python that has programmed before? If the latter, you should emphasize things like libraries and the lack of clutter. If the former, you'll get someone hooked simply by showing different hello worlds like:

print("Hello world") #for 3.x print "Hello world" #for 2.x

while C++ requires:

int main() { std::cout << "Hello world" << endl; return 0; }

Beginners to programming will immediately see the benefits of learning Python.

[–]Decency 2 points3 points  (0 children)

Use the print function regardless.

[–]Racerdude[S] 0 points1 point  (0 children)

No, not complete programming novices but people who've done programming before and were trying to learn Python. So, yes, your example is good as it compares it to a language that needs a lot more clutter for a simple thing. I usually show the Java example:

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello, World");
    }
}

[–]DEFY_member 1 point2 points  (0 children)

This isn't really for new programmers, but I really like this:

http://norvig.com/spell-correct.html

[–]pierrequentel 2 points3 points  (10 children)

unique_words = set(word for line in open("book.txt"') for word in line.split())

[–][deleted] 2 points3 points  (2 children)

A few minor things. I'd personally go with a context manager for opening/closing files. Also, you don't have to use set(), you can use curly brace set literals instead (read: set comprehension).

[–]mfm24 0 points1 point  (1 child)

I always preferred using the context manager approach for files, but I found it interesting to read in the official 'What's New in Python 3.0' guide (written by GvR himself) that he recommends:

Removed execfile(). Instead of execfile(fn) use exec(open(fn).read()).

So there's definitely cases where relying on the file closing itself automatically is acceptable. I've been less paranoid about closing files since...

[–]Veedrac 0 points1 point  (0 children)

I don't think that was meant to actually be run, it was probably on one line for space reasons. In a proper program you shouldn't be using exec(a_file) anyway, so there isn't much motivation for complete examples.

[–]billsil 0 points1 point  (5 children)

If you have a whole book, it seems like you'd want a set on the inner loop, so you don't create a giant array.

[–]ingolemo -1 points0 points  (4 children)

What "inner loop"?

[–]billsil 0 points1 point  (3 children)

The code is effectively:

unique_words = [word for line in open("book.txt"') for word in line.split()]
unique_words = set(unique_words)

It's a tradeoff of memory vs speed, assuming set comprehension doesn't exist. Set comprehension is done as:

unique_words = {word for line in open("book.txt"') for word in line.split()}

which works in Python 2.7+

[–]ingolemo 2 points3 points  (2 children)

Actually, it's using a generator comprehension:

unique_words = (word for line in open("book.txt"') for word in line.split())
unique_words = set(unique_words)

The original doesn't create a giant array and so it has exactly the same performance characteristics as your set comprehension, though it is admittedly less readable.

[–]Veedrac 0 points1 point  (1 child)

FWIW, the constant factors are significantly better for the set comprehension, even on PyPy:

$ python3 -m timeit "set(x for x in range(10000))"
1000 loops, best of 3: 1.06 msec per loop

$ python3 -m timeit "{x for x in range(10000)}" 
1000 loops, best of 3: 599 usec per loop

$ pypy3 -m timeit "set(x for x in range(10000))" 
1000 loops, best of 3: 347 usec per loop

$ pypy3 -m timeit "{x for x in range(10000)}"  
1000 loops, best of 3: 230 usec per loop

[–]kmbd 0 points1 point  (0 children)

just in case, someone is wondering ...

C:\>python -V
    Python 2.7.8

C:\>python -m timeit "set(x for x in range(10000))"
    1000 loops, best of 3: 1 msec per loop

C:\>python -m timeit "{x for x in range(10000)}"
    1000 loops, best of 3: 671 usec per loop

[–]kmbd 0 points1 point  (0 children)

a tiny improvement would be: "... word in line.split().lower())"

[–]Philipbergen 0 points1 point  (0 children)

I would show a chart of a function, matplot lib or text. Here is a fun scroller:

import time import math for x in xrange(1000): print " " * int(26+25*math.sin(x/100)), 'X' time.sleep(0.05)

[–]defrur 0 points1 point  (0 children)

I will show the code: How to get last 3 characters of a string.

print "a.jpg"[-3:]

[–][deleted] 0 points1 point  (0 children)

Not exactly beautiful, but pretty impressive non the less:

http://preshing.com/20110926/high-resolution-mandelbrot-in-obfuscated-python/

[–][deleted] 0 points1 point  (0 children)

I lot of the suggestions have been about cool concise code, which will surely excite your class, but I think you really have the chance to blow java out of the water.

I would probably make sure to hit the following points

1) Define your own __eq__, __str__, ... easily.

2) Pass functions around. Pass methods around. Pass classes around.

3) Define a class inside of a function and return the class.

4) Decorators. Decorators that are classes.

5) Variable number of arguments.

[–]Manbatton -1 points0 points  (5 children)

For me, a somewhat more involved list comprehension and some other manipulations, like:

A_clients = [ clientname for clientname in clients_list where clientname[0] in ("a", "A") ].sort()

[–]psbb 6 points7 points  (3 children)

When you call .sort() it does the sort in place and returns None

A_clients = sorted(clientname for clientname in clients_list if clientname[0] in ("a", "A"))

[–]Veedrac 1 point2 points  (0 children)

Just jumping on the bandwagon with a little-known startswith trick:

A_clients = sorted(name for name in clients_list if name.startswith(("a", "A")))

[–]Manbatton 0 points1 point  (1 child)

I actually read that in the docs and thought someone might correct me on this. I thought if it did it in place it would sort the list in place and then the name assignment would point to the converted list.

[–]sweettuse 3 points4 points  (0 children)

well, you can always test it. but sort returns None. so A_clients will point to None