All published worksheets from http://sagenb.org
Image: ubuntu2004
581d - 2010-10-14:
A Crash course in Python, for people who (think they) know Python.
Today: Functions and Classes
NOTE: This worksheet should be run in Python mode. Adjust the dropdown at the top of the worksheet to make sure it is in that mode.
Functions
A big gotcha (explain):
Right thing to do is this:
How to do variable number of arguments and keywords:
You can magically turn a tuple or dictionary into the inputs to a function using * and **:
When you explicitly specify the input variable names, you can give them in any order:
A function can sometimes tell whether it was called with the input variable explicitly specified via a keyword or not. So there is a difference between f(7,20) and f(a=7,b=20).
How to return multiple values.
This actually looks exactly like what you do in Magma, but it is much different (and better) than Magma, since really a tuple is returned, and Python does tuple unpacking:
Python functions can be easily passed around, and you can figure out some things about them in some cases.
You can attach extra attributes to a function itself. (This only works with functions defined in Python.)
You can't attach attributes to functions that are "builtin".
Another gotcha is recursion, which does not scale in Python.
So watch out and be careful when writing recursive functions that you only use them when the depth of the recursion is bounded by 1000. Or, simply increase the recursionlimit as illustrarted below.
Style: Go through http://docs.python.org/tutorial/controlflow.html#intermezzo-coding-style
The following function illustrates all the points.
Aliasing:
From the Python documentation: "Objects have individuality, and multiple names (in multiple scopes) can be bound to the same object. This is known as aliasing in other languages. This is usually not appreciated on a first glance at Python, and can be safely ignored when dealing with immutable basic types (numbers, strings, tuples). However, aliasing has a possibly surprising effect on the semantics of Python code involving mutable objects such as lists, dictionaries, and most other types. This is usually used to the benefit of the program, since aliases behave like pointers in some respects. For example, passing an object is cheap since only a pointer is passed by the implementation; and if a function modifies an object passed as an argument, the caller will see the change — this eliminates the need for two different argument passing mechanisms as in Pascal."
This is surprising and different than every other language I know. You must understand this point completely, or you'll get seriously tripped up.
Example
Hey, what just happened to v?!
Classes
Inheritence
Question: How do we call the f method defined in the superclass?
One way: explicitly get the superclass's f method, and call it with d as input.
Approach 2: use the super function. This makes no explicit reference to MyClass, which is nice.
Huh!? See http://stackoverflow.com/questions/489269/python-super-raises-typeerror-why. The problem is that super only operators on new style classes, i.e., classes that derive from object. (Note: In Python 3.x, all classes are new style classes.)
Multiple Inheritence: new versus old style classes
----------- | | | O | | / \ | - X Y / | / | / | / |/ A B \ / C
Old style classes -- allow ambiguous class hierarchies:
New style classes don't allow this:
Method Resolution Order:
Given any Python class C, there is a linearly ordered list of the superclasses of C that Python computes, called the MRO "Method Resolution Order". When you try to call a function of (an instance of) C, Python just checks for that function in each of the methods of the classes in the MRO, in order.
- Different for old and new style classes. Old style classes have a very easy MRO, but it has quite bad theoretical properties. "For old-style classes, the only rule is depth-first, left-to-right."
- For new style classes see http://www.python.org/download/releases/2.3/mro/ for a detailed discussion on the new style MRO.
- Fortunately, you can simply ask a new style class for its MRO. When in doubt, just do this.
Another:
6 --- Level 3 | O | / --- \ / | \ / | \ / | \ --- --- --- Level 2 2 | E | 4 | D | | F | 5 --- --- --- \ / \ / \ / \ / \ / \ / --- --- Level 1 1 | B | | C | 3 --- --- \ / \ / --- Level 0 0 | A | ---
Private Variables.
This is done in Python via "mangling".
Easily thwarted:
From experience I can tell you most people really hate the use of these mangled private variables. It is much better to just use a single underscore, which is meant as a convention "However, there is a convention that is followed by most Python code: a name prefixed with an underscore (e.g. _spam) should be treated as a non-public part of the API (whether it is a function, a method or a data member). It should be considered an implementation detail and subject to change without notice."