Programming in Python: selected questions and answers. Updated frequently, refresh your browser. From the course, http://staff.washington.edu/jon/python-course/ Here are answers to some of the questions asked in the weekly reports or in personal email. Some other questions will be answered in class (perhaps as part of a lecture). Not all questions will be answered, due to limited time. This does not reflect on the worthiness of the unanswered questions. Downey's solutions to some of his textbook exercises: http://greenteapress.com/thinkpython/code/ Other collections of Python questions and answers: http://docs.python.org/faq/programming http://mail.python.org/pipermail/tutor/ http://stackoverflow.com/questions/tagged/python Each question and its answer are numbered: Q.2.1 and A.2.1 etc. All Q.2 and A.2 are from week 2, etc., so you can search for a given week. Dec 11 (week 9) Q.9.4: I have a list of lists, say 'mylist', and I am interested in sorting it, I use "mylist.sort()" and it works well but it sorts by the first index. For example, let mylist =[[1,2],[3,1],[2,5],[8,1],[4,2]], then "mylist.sort()" sorts mylist by the first index: [[1, 2], [2, 5], [3, 1], [4, 2], [8, 1]]. How can I sort mylist by the second index? A.9.4 You can use the optional 'key' keyword parameter to specify or define a key function. The list is sorted such that the sorted list is ordered by the values obtained by applying the key function to each list element (but the original list elements appear in the sorted list also). Here the key function should return the second element of each tuple, we define it with a lambda expression: mylist.sort(key = lambda t: t[1]) Likewise, if you have a list of objects where each object has an attribute named 'i' you sort by the value of this attribute this way: objectlist.sort(key = lambda t: t.i) The 'key' and other sort parameters are explained in more detail here: Sorting HOW TO http://docs.python.org/howto/sorting.html See also sort.py at the class website. Q.9.3: 2. In the vector.py example, you used super(vector,self).__repr__() What is the meaning of "super(vector,self)"? A.9.3: It refers to the superclass or base class, that is, list. In this code: 'vector(%s)' % super(vector,self).__repr__() this has the effect of calling list.__repr__(), then inserting the result in place of the %s in 'vector(%s)' Q.9.2: In the function def f(**kwargs) what is the underlying behavior of ** ? A.9.2: It gathers multiple keyword arguments into a dictionary: def f(**kwargs): print kwargs Then f('a'=1, 'b'=2) prints { 'a':1, 'b':2 } You can also use ** in a function invocation to scatter a dictionary to positional parameters: def g(a,b,c): print a,b,c d = { 'c':3, 'b':2, 'a':1 } Then g(d) prints 1,2,3 See also parameters.py on the course website. Q.9.1: Since Python isn't a statically-typed language, is it a recommended practice to put asserts or other forms of checking into functions that implicitly expect certain types (or is try/except preferred)? A.9.1: I don't recall seeing many asserts or checks in function bodies. Sometimes there is a try/except around the function *call* (not in the function body). So typical Python style seems to be to omit any checks in the function itself, leaving the caller to use try/except if they wish. Note that in Python, the type of the argument is not what you really need to know. The important thing is whether the argument provides the operations that the function body uses, and the type doesn't tell you that (due to duck typing). For example, your function body might use +, so the argument has to support that, but the argument might not even be a numeric type, it might be a list, or it might belong to some class you never heard of where the programmer defined an __add__ method, that might make sense in your function, even if you didn't anticipate it. In my own code, I sometimes do put asserts at the beginning of function bodies, to check types but also to check other conditions. I think of it as documentation --- it's no more difficult to write an assert statement than write a comment. Dec 5 (week 8) Q.8.1: Is there some way to enforce that the objects (that belong to the same class) all have the same data members? A.8.1: Yes, use the __slots__ attribute. See in http://docs.python.org/reference/datamodel.html#special-method-names and use a search engine to find examples. Nov 15 (Week 5) Q.5.3: (Install problems, versions and dependencies) It is not always straightforward to figure out what versions of Python that third-party packages such as NumPy requiire. It turns out that NumPy works with 2.6.x. Do you have any suggestions for dealing with these issues, other than trial-and-error? A.5.3: For some operating systems there are package managers that automatically keep track of dependencies, for example Synaptic/apt for Ubuntu and other Debian-like Linux distributions, or Macports for Mac OS X. IF your operating system has a package manager and IF the package you want is known to the package manager, then when you install a package it finds all the dependencies (including earlier Python versions) and (optionally) installs them too. I'm not aware of anything like this for Windows, unfortunately. Nov 14 (Week 5) Q.5.2: (Unicode) I copied and pasted the poem about Eric the half a bee into a text file ... on output, the word D'you is rendered 'd\xe2\x80\x99you'. \xe2\x80\x99 is unicode for the forward-quote character. How to deal with this? A.5.2: I recommend avoiding the whole unicode issue by just converting the file to ASCII by hand. Just load the poem into your favorite editor, change that word to D'you or D`you, using the single quote or backquote key on your keyboard. Then save that, now it should be ASCII only. This unicode/character encoding issue is complicated. I think it's only worth getting into if you need to work with a lot of foreign language text. If you do go that route, here are some pertinent links: Unicode HOWTO http://docs.python.org/howto/unicode.html Unicode in Python, completely demystified http://farmdev.com/talks/unicode/ How to Use UTF-8 with Python (with several more pertinent links at the end) http://evanjones.ca/python-utf8.html Nov 13 (Week 5) Q.5.1: What is the best way to copy a list? A.5.1: The unobvious but canonical solution is t = s[:]. You assign the slice from the beginning to the end to the new list! Let's try it, confirm the new list t doesn't share contents with the original s: >>> s = [ 1, 2, [3,4], 5] >>> t = s[:] >>> t [1, 2, [3, 4], 5] >>> s == t True >>> s is t False >>> s[1] = 99 >>> s == t False >>> s [1, 99, [3, 4], 5] >>> t [1, 2, [3, 4], 5] So it looks like we're not sharing. BUT --- >>> s[2][1] = 88 >>> s [1, 99, [3, 88], 5] >>> t [1, 2, [3, 88], 5] so we're still sharing the nested list. t = s[:] only works for flat (unnested) lists. To copy nested lists we need a recursive function. A general solution is provided by the copy module's deepcopy function, which handles all nested structures, not just lists. Nov 9 (Week 4) Q.4.5: What is PYTHONPATH? How do I set it up? A.4.5: PYTHONPATH is an environment variable that the Python interpreter uses to search for modules that you import. When Python executes 'import mymodule' it looks for a file named mymodule.py ... where? It looks in the current working directory and in certain special directories, which is often sufficient without you having to do anything more. But if you have modules in other directories that you want Python to search, you can add to the search path by defining (or redefining) PYTHONPATH at your system's command prompt (not the python interpreter prompt). The command is system dependent. Here are some examples (from one of my projects, the exact path contents would be different for you): For Windows (in a cmd window): set PYTHONPATH=%PYTHONPATH%;C:\Users\jon\Documents\repy_v2\repy;C:\Users\jon\Doc uments\repy_v2\portability For Unix/Linux/Mac (using the bash shell): export PYTHONPATH=$PYTHONPATH:/Users/jon/repy_v2/repy:/Users/jon/repy_v2/portabi lity To show the path that python actually uses in a session: >>> import sys >>> sys.path ... If you assigned PYTHONPATH using a command like one of the above, you should see the directories you named in the output here. Q.4.4: How to "slice" a word by a character? How to "slice" a file by backspaces? A.4.4: You probably want the string split (not slice) method. It takes a string and a separator string (which can be one character but needn't be) and returns a list of strings. For example, to split a string by spaces: >>> s = 'abc def' >>> s.split(' ') ['abc', 'def'] The backspace character is indicated '\b'. You can read an entire file into a string using read(), so something like this should work: >>> s = open('myfile.txt').read() >>> s.split('\b') ... Q.4.3: Is there any way to reload a module into a running Python session (after editing it to fix an error)? A.4.3: Not really. You can try reload(), or repeat import *then* reload, but these do not always have the intended effect. The most certain way is to just start a new Python session. That's what IDLE does. Nov 6 (Week 4) Q.4.2: Are the solutions to the textbook exercises available anywhere? A.4.2: Some solutions are at http://greenteapress.com/thinkpython/code/ Q.4.1: What about Python 2.x vs. 3.x ? A.4.1: Most big libraries (NumPy, SciPy, ....) still use 2.x so I'm sticking with that for now. I don't have any experience with 3.x. These pages may be helpful: What's New In Python 3.0 http://docs.python.org/release/3.0.1/whatsnew/3.0.html On Teaching Programming With Python 3.0 http://www.comp.leeds.ac.uk/nde/papers/teachpy3.html Ask HN: start with python 2.6 or 3? http://news.ycombinator.com/item?id=687087 Q.4.0: Why does the expression 'None or False' return False, but 'False or None' does not return anything? A.4.0. Actually, 'False or None' returns 'None', but the interpreter prints nothing (try typing just None to the interpreter) . 'or' always returns one of its arguments, see A.3.3 below. Week 3 Q.3.0: What are some other sources of Python exercises and projects (besides the Downey textbook)? Also, what are some tutorials that use less math than Downey? A.3.0: Here are a few I've heard of. I haven't tried them, so these are not recommendations, they are just for your information. Google python exercises or prthon projects turns up a lot more. Learning to Program by Alan Gauld (no exercises) http://www.freenetpages.co.uk/hp/alan.gauld/ A Python Course (includes exercises, might use less math than Downey) http://www.upriss.org.uk/python/PythonCourse.html Basic Python Exercises (other exercises linked to list at lower left) http://code.google.com/edu/languages/google-python-class/exercises/basic.html The Python Challenge (all exercises, treasure-hunt format) http://www.pythonchallenge.com/ Project Euler (math exercises, challenging) http://projecteuler.net/ Q.3.1: How to represent enumerated types in Python? A.3.1: If you just need symbols, you could use literal strings: if color == 'green': ... If enumerations must have numeric values a la C you could assign variables: red, yellow, green = range(3) This is equivalent to the tuple assignment red, yellow, green = 0, 1, 2 which is equivalent to the sequence of assignments red = 0; yellow = 1; green = 2 If you need type checking a la C# you could define a class Color with attributes Color.red etc. Q.3.2: How to do type checking of function arguments? A.3.2: You could use assert with isinstance: def f(i): assert isinstance(i, int) # raise AssertionError if i is not int return i + 1 Q.3.3: Does 'and' evaluate both of its arguments? A.3.3: Not always - it uses "short circuit evaluation" which returns as soon as it has the answer. From http://docs.python.org/reference/expressions.html#boolean-operations The expression x and y first evaluates x; if x is false, its value is returned; otherwise, y is evaluated and the resulting value is returned. ... (Note that neither and nor or restrict the value and type they return to False and True, but rather return the last evaluated argument. This is sometimes useful. ... Recall that any value can be interpreted as true or false; for example, nonzero numbers and nonempty collections are true, etc. Week 2 Q.2.0: Is there a computerized means of converting source code from Python 2 to Python 3? A.2.0: Yes, it's called 2to3: http://docs.python.org/py3k/library/2to3.html Q.2.1: What's this? >>> 'Hello', 'World' ('Hello', 'World') A.2.1: It's a tuple. The comma operator ',' creates a tuple. You have created a tuple of two strings. Tuples are discussed in Ch. 12 in the textbook, which we will cover in week 5. Q.2.2: What is the syntactic significance of this result? >>> type(17) A.2.2 This is just how the Python interpreter prints out the the int (integer) type. Also: >>> int Week 1 Q.1.2: My question is the need to account for an additional space when using the print statement with a comma. Is there a way to avoid extra space when printing multiple variables separated by commas? A.1.2: The usual way to get more control over printing is to use format strings. So, for example, to print the values of x and y with no spaces between, this should work: print '%s%s' % (x, y) In the textbook, the index has an entry 'format strings' but the book barely explains them. The Python 2.6 Quick Reference linked to the course home page (in the Readings section) has more, and the Python Tutorial linked in that same section also explains more in section 7.1 (what I recommend above is Old String Formatting, section 7.1.1). Q.1.3: I found in basics.py: if x: print x, ' indicates True' else: print x, ' indicates False' I saved this code in a file and when I tried to run it, it gave me this error message: Traceback (most recent call last): File "C:/Python26/week1.py", line 1, in if x: NameError: name 'x' is not defined A.1.3: In your module you need to define x before you use it, for example by an assignment statement like this: x = 'Hello' Notice that this line does appear in my basics.py. Put this line (or something like it) before the if statement in your file.py and it should work.