Bonus Chapter 43

Using Python

As PHP has come to dominate the world of web scripting, Python is increasingly dominating the domain of command-line scripting. Python’s precise and clean syntax makes it one of the easiest languages to learn, and it allows programmers to code more quickly and spend less time maintaining their code. Whereas PHP is fundamentally similar to Java and Perl, Python is closer to C and Modula-3, and so it might look unfamiliar at first.

This chapter constitutes a quick-start tutorial to Python, designed to give you all the information you need to put together basic scripts and to point you toward resources that can take you further.

Two versions of Python are out in the wild right now. Python version 2.x reached end-of-life in 2019, although you are likely to see it in the wild for a while longer. Python 3.x is now the default version everywhere, including in Ubuntu, although Python 2.x will likely not yet be completely removed for Ubuntu 20.04; it will have to be installed intentionally alongside Python 3.x if it is needed.

Python 3.x is not backward compatible, and most programs written in or for 2.x need some work to run on 3.x, which is why the previous version is still available. However, most companies are working hard to update their code, such as LinkedIn, which announced in January 2020 that it “retired Python 2 and improved developer happiness” (https://engineering.linkedin.com/blog/2020/how-we-retired-python-2-and-improved-developer-happiness).

This chapter tries to note places where significant differences exist between 2.x and 3.x. If you are learning Python for the first time, start with a look at the 3.x series because it is the future.

Note

This chapter provides a very elementary introduction to Python. For that reason, nearly everything we cover is identical in both 2.x and 3.x. We mention the differences earlier and in a couple of notes that follow so that readers who want to learn more will not be surprised later. Unless noted otherwise, you should find what we say in this chapter applies to either version.

Python on Linux

Most versions of Linux and UNIX, including macOS, come with Python preinstalled. This is partially for convenience because it is such a popular scripting language—and it saves having to install it later if the user wants to run a script—and partially because many vital or useful programs included in Linux distributions are written in Python. For example, the Ubuntu Software Center is a Python program.

The Python binary is installed in /usr/bin/python (or /usr/bin/python3); if you run that, you enter the Python interactive interpreter, where you can type commands and have them executed immediately. Although PHP also has an interactive mode (use php -a to activate it), it is neither as powerful nor as flexible as Python’s.

As with Perl, PHP, and other scripting languages, you can also execute Python scripts by adding a shebang line (#!) to the start of your scripts that point to /usr/bin/python and then setting the file to be executable.

The third way to run Python scripts is through mod_python, which is an Apache module that embeds the Python interpreter into the HTTP server, allowing you to use Python to write web applications. You can install this from the Ubuntu repositories.

We use the interactive Python interpreter for this chapter because it provides immediate feedback on commands as you type them, so it is essential that you become comfortable using it. To get started, open a terminal and run the command python. You should see something like this, perhaps with different version numbers and dates:

matthew@seymour:~$ python
Python 3.6.4 (default, Dec27 2017, 13:02:49)
[GCC 7.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>

The >>> is where you type your input, and you can set and get a variable like this:

>>> python = 'great'
>>> python'great'
great
>>>

On the first line in this example, the variable python is set to the text great, and on the second line, you read back that value from the variable simply by typing the name of the variable you want to read. The third line shows Python printing the variable; on the fourth line, you are back at the prompt to type more commands. Python remembers all the variables you use while in the interactive interpreter, which means you can set a variable to be the value of another variable.

When you are done, press Ctrl+D to exit. At this point, all your variables and commands are forgotten by the interpreter, which is why complex Python programs are always saved in scripts.

The Basics of Python

Python is a language wholly unlike most others, and yet it is so logical that most people can pick it up quickly. You have already seen how easily you can assign strings, but in Python, nearly everything is that easy—as long as you remember the syntax.

Numbers

The way Python handles numbers is more precise than in some other languages. It has all the normal operators—such as + for addition, - for subtraction, / for division, and * for multiplication—but it adds % for modulus (division remainder), ** for raise to the power, and // for floor division. It is also specific about which type of number is being used, as this example shows:

>>> a = 5
>>> b = 10
>>> a * b
50
>>> a / b
0
>>> b = 10.0
>>> a / b
0.5
>>> a // b
0.0

The first division returns 0 because both a and b are integers (whole numbers), so Python calculates the division as an integer, giving 0. By converting b to 10.0, Python considers it to be a floating-point number, and so the division is now calculated as a floating-point value, giving 0.5. Even with b being a floating point, using //—floor division—rounds it down.

Using **, you can easily see how Python works with integers:

>>> 2 ** 30
1073741824
>>> 2 ** 31
2147483648L

The first statement raises 2 to the power of 30 (that is, 2 times 2 times 2 times 2…), and the second raises 2 to the power of 31. Notice how the second number has a capital L on the end of it; this is Python telling you that it is a long integer. The difference between long integers and normal integers is slight but important: Normal integers can be calculated using simple instructions on the CPU, whereas long integers—because they can be as big as you need them to be—need to be calculated in software and therefore are slower.

When specifying big numbers, you need not put the L at the end as Python figures it out for you. Furthermore, if a number starts off as a normal number and then exceeds its boundaries, Python automatically converts it to a long integer. The same is not true the other way around: If you have a long integer and then divide it by another number so that it could be stored as a normal integer, it remains a long integer:

>>> num = 999999999999999999999999999999999L
>>> num = num / 1000000000000000000000000000000
>>> num
999L

You can convert between number types by using typecasting, like this:

>>> num = 10
>>> int(num)
10
>>> float(num)
10.0
>>> long(num)
10L
>>> floatnum = 10.0
>>> int(floatnum)
10
>>> float(floatnum)
10.0
>>> long(floatnum)
10L

You need not worry about whether you are using integers or long integers; Python handles it all for you, so you can concentrate on getting the code right. In the 3.x series, the Python integer type automatically provides extra precision for large numbers, whereas in 2.x you use a separate long integer type for numbers larger than the normal integer type is designed to handle.

More on Strings

Python stores a string as an immutable sequence of characters—a jargon-filled way of saying that “it is a collection of characters that, once set, cannot be changed without creating a new string.” Sequences are important in Python. There are three primary types, of which strings are one, and they share some properties. (Mutability makes a lot of sense when you learn about lists in the next section.)

As you saw in the previous example, you can assign a value to strings in Python with just an equal sign, like this:

>>> mystring = 'hello';
>>> myotherstring = "goodbye";
>>> mystring'hello'
>>> myotherstring;'goodbye'
>>> test = "Are you really Jayne Cobb?"
>>> test
"Are you really Jayne Cobb?"

The first example encapsulates the string in single quotation marks, and the second and third examples encapsulate the string in double quotation marks. However, printing the first and second strings shows them both in single quotation marks because Python does not distinguish between the two types. The third example is the exception; it uses double quotation marks because the string itself contains a single quotation mark. Here, Python prints the string with double quotation marks because it knows it contains the single quotation mark.

Because the characters in a string are stored in sequence, you can index into them by specifying the character you are interested in. As in most other languages, in Python these indexes are zero based, which means you need to ask for character 0 to get the first letter in a string. Here is an example:

>>> string = "This is a test string"
>>> string
'This is a test string'
>>> string[0]
'T'
>>> string [0], string[3], string [20]
('T', 's', 'g')

The last line shows how, with commas, you can ask for several indexes at the same time. You could print the entire first word using the following:

>>> string[0], string[1], string[2], string[3]
('T', 'h', 'I', 's')

However, for that purpose, you can use a different concept: slicing. A slice of a sequence draws a selection of indexes. For example, you can pull out the first word like this:

>>> string[0:4]
'This'

The syntax here means “take everything from position 0 (including 0) and end at position 4 (excluding it).” So, [0:4] copies the items at indexes 0, 1, 2, and 3. You can omit either side of the indexes, and it will copy either from the start or to the end:

>>> string [:4]
'This'
>>> string [5:]
'is a test string'
>>> string [11:]
'est string'

You can also omit both numbers, and it gives you the entire sequence:

>>> string [:]'This is a test string'

Later you learn precisely why you would want to do this, but for now we look at a number of other string intrinsics that will make your life easier. For example, you can use the + and * operators to concatenate (join) and repeat strings, like this:

>>> mystring = "Python"
>>> mystring * 4
'PythonPythonPythonPython'
>>> mystring = mystring + " rocks! "
>>> mystring * 2
'Python rocks! Python rocks! '

In addition to working with operators, Python strings come with a selection of built-in methods. You can change the case of the letters with capitalize() (uppercases the first letter and lowercases the rest), lower() (lowercases them all), title() (uppercases the first letter in each word), and upper() (uppercases them all). You can also check whether strings match certain cases with islower(), istitle(), and isupper(); this also extends to isalnum() (which returns true if the string is letters and numbers only) and isdigit() (which returns true if the string is all numbers).

This example demonstrates some of these in action:

>>> string
'This is a test string'
>>> string.upper()
'THIS IS A TEST STRING'
>>> string.lower()
'this is a test string'
>>> string.isalnum()
False
>>> string = string.title()
>>> string
'This Is A Test String'

Why did isalnum() return false? Doesn’t the string contain only alphanumeric characters? Well, no. There are spaces in there, which is what is causing the problem. More importantly, this example calls upper() and lower(), and they are not changing the contents of the string but just returning the new value. So, to change the string from This is a test string to This Is A Test String, you have to assign it back to the string variable.

Another really useful and kind of cool thing you can do with strings is triple quoting. This way, you can easily create strings that include both double- and single-quoted strings, as well as strings that span more than one line, without having to escape a bunch of special characters. Here’s an example:

>>>foo = """
..."foo"
...'bar'
...baz
...blippy
..."""
>>>foo
'
"foo"
'bar'
baz
blippy
'
>>>

Although this is intended as an introductory guide, the capability to use negative indexes with strings and slices is a pretty neat feature that deserves a mention. Here’s an example:

>>>bar="news.google.com"
>>>bar[-1]
'm'
>>>bar[-4:]
'.com'
>>>bar[-10:-4]
'google'
>>>

One difference between Python 2.x and 3.x is the introduction of new string types and method calls. This doesn’t affect what we share here but is something to pay attention to as you work with Python.

Lists

Python’s built-in list data type is a sequence, like strings. However, lists are mutable, which means you can change them. A list is like an array in that it holds a selection of elements in a given order. You can cycle through them, index into them, and slice them:

>>> mylist = ["python", "perl", "php"]
>>> mylist
['python', 'perl', 'php']
>>> mylist + ["java"]
["python", 'perl', 'php', 'java']
>>> mylist * 2
['python', 'perl', 'php', 'python', 'perl', 'php']
>>> mylist[1]
'perl'
>>> mylist[1] = "c++"
>>> mylist[1]
'c++'
>>> mylist[1:3]
['c++', 'php']

The brackets notation is important: You cannot use parentheses (()) or braces ({}) for lists. Using + for lists is different from using + for numbers. Python detects that you are working with a list and appends one list to another. This is known as operator overloading, and it is part of what makes Python so flexible.

Lists can be nested, which means you can put a list inside a list. However, this is where mutability starts to matter, and so this might sound complicated. Recall that an immutable string sequence is a collection of characters that, once set, cannot be changed without creating a new string. Lists are mutable, as opposed to immutable, which means you can change a list without creating a new list. This becomes important because Python, by default, copies only a reference to a variable rather than the full variable. Consider this example:

>>> list1 = [1, 2, 3]
>>> list2 = [4, list1, 6]
>>> list1
[1, 2, 3]
>>> list2
[4, [1, 2, 3], 6]

This example shows a nested list. list2 contains 4, then list1, then 6. When you print the value of list2, you can see that it also contains list1. Now, let’s proceed on from that:

>>> list1[1] = "Flake"
>>> list2
[4, [1, 'Flake', 3], 6]

In the first line, you set the second element in list1 (remember that sequences are zero based!) to be Flake rather than 2; then you print the contents of list2. As you can see, when list1 changes, list2 is updated, too. The reason for this is that list2 stores a reference to list1 as opposed to a copy of list1; they share the same value.

You can see that this works both ways by indexing twice into list2, like this:

>>> list2[1][1] = "Caramello"
>>> list1
[1, 'Caramello', 3]

The first line says, “Get the second element in list2 (list1) and the second element of that list and set it to be ‘Caramello’.” Then list1’s value is printed, and you can see that it has changed. This is the essence of mutability: You are changing a list without creating a new list. However, editing a string creates a new string, leaving the old one unaltered. Here is an example:

>>> mystring = "hello"
>>> list3 = [1, mystring, 3]
>>> list3
[1, 'hello', 3]
>>> mystring = "world"
>>> list3
[1, 'hello', 3]

Of course, this raises the question of how you copy without references when references are the default. The answer, for lists, is that you use the [:] slice, covered earlier in this chapter. This slices from the first element to the last, inclusive, essentially copying it without references. Here is how it looks:

>>> list4 = ["a", "b", "c"]
>>> list5 = list4[:]
>>> list4 = list4 + ["d"]
>>> list5
['a', 'b', 'c']
>>> list4
['a', 'b', 'c', 'd']

Lists have their own collections of built-in methods, such as sort(), append(), and pop(). The latter two add and remove single elements from the end of the list, and pop() also returns the removed element. Here is an example:

>>> list5 = ["nick", "paul", "Julian", "graham"]
>>> list5.sort()
>>> list5
['graham', 'julian', 'nick', 'paul'']
>>> list5.pop()'paul'
>>> list5
['graham', 'julian', 'nick']

>>> list5.append("Rebecca")

In addition, one interesting method of strings returns a list: split(). This takes a character to split by and then gives you a list in which each element is a chunk from the string. Here is an example:

>>> string = "This is a test string";
>>> string.split(" ")
['This', 'is', 'a', 'test', 'string']

Lists are used extensively in Python, although this is slowly changing as the language matures. The way lists are compared and sorted has changed in 3.x, so be sure to check the latest documentation when you attempt to perform these tasks.

Dictionaries

Unlike a list, a dictionary is a collection with no fixed order. Instead, it has a key (the name of the element) and a value (the content of the element), and Python places a dictionary wherever it needs to for maximum performance. When defining dictionaries, you need to use braces ({}) and colons (:). You start with an opening brace and then give each element a key and a value, separated by a colon, like this:

>>> mydict = { "perl" : "a language", "php" : "another language" }
>>> mydict
{'php': 'another language', 'perl': 'a language'}

This example has two elements, with keys perl and php. However, when the dictionary is printed, you find that php comes before perl; Python hasn’t respected the order in which you entered them. You can index into a dictionary by using the normal code:

>>> mydict["perl"]'a language'

However, because a dictionary has no fixed sequence, you cannot take a slice or an index by position.

Like lists, dictionaries are mutable and can also be nested; however, unlike with lists, you cannot merge two dictionaries by using +. This is because dictionary elements are located using the key. Therefore, having two elements with the same key would cause a clash. Instead, you should use the update() method, which merges two arrays by overwriting clashing keys.

You can also use the keys() method to return a list of all the keys in a dictionary.

Subtle differences exists between how dictionaries are used in 3.x compared to in 2.x, such as the need to make list calls to produce all values at once so they may be printed. Again, be sure to check the latest documentation as you move ahead because there are several of these changes in functionality, with some tools now behaving differently or even disappearing and other new dictionary tools being added. Some of those features have been backported; for example, Python 2.7 received support for ordered dictionaries, backported from Python 3.1 (see https://docs.python.org/dev/whatsnew/2.7.html#pep-0372).

Conditionals and Looping

So far, we have just been looking at data types, which should show you how powerful Python’s data types are. However, you cannot write complex programs without conditional statements and loops.

Python has most of the standard conditional checks, such as > (greater than), <= (less than or equal to), and == (equal), but it also adds some new ones, such as in. For example, you can use in to check whether a string or a list contains a given character or element:

>>> mystring = "J Random Hacker"
>>> "r" in mystring
True
>>> "Hacker" in mystring
True
>>> "hacker" in mystring
False

This example demonstrates how strings are case sensitive. You can use the equal operator for lists, too:

>>> mylist = ["soldier", "sailor", "tinker", "spy"]
>>> "tailor" in mylist
False

Other comparisons on these complex data types are done item by item:

>>> list1 = ["alpha", "beta", "gamma"]
>>> list2 = ["alpha", "beta", "delta"]
>>> list1 > list2
True

In this case, list1’s first element (alpha) is compared against list2’s first element (alpha) and, because they are equal, the next element is checked. That is equal also, so the third element is checked, which is different. The g in gamma comes after the d in delta in the alphabet, so gamma is considered greater than delta, and list1 is considered greater than list2.

Loops come in two types, and both are equally flexible. For example, the for loop can iterate through letters in a string or elements in a list:

>>> string = "Hello, Python!"
>>> for s in string: print s,
...
H e l l o ,   P y t h o n !

The for loop takes each letter in a string and assigns it to s. This is then printed to the screen using the print command, but note the comma at the end; it tells Python not to insert a line break after each letter. The ellipsis (...) is there because Python allows you to enter more code in the loop; you need to press Enter again here to have the loop execute.

You can use the same construct for lists:

>>> mylist = ["andi", "rasmus", "zeev"]
>>> for p in mylist: print p
...
andi
rasmus
zeev

Without the comma after the print statement, each item is printed on its own line.

The other loop type is the while loop, and it looks similar:

>> while 1: print "This will loop forever!"
...
This will loop forever!
This will loop forever!
This will loop forever!
This will loop forever!
This will loop forever!
(etc)
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
KeyboardInterrupt
>>>

That is an infinite loop (it carries on printing that text forever), so you need to press Ctrl+C to interrupt it and regain control.

If you want to use multiline loops, you need to get ready to use your Tab key: Python handles loop blocks by recording the level of indent used. Some people find this odious; others admire it for forcing clean coding on users. Most of us, though, just get on with programming.

Here is an example:

>>> i = 0
>>> while i < 3:
...     j = 0
...     while j < 3:
...             print "Pos: " + str(i) + "," + str(j) + ")"
...             j += 1
...     i += 1
...
Pos: (0,0)
Pos: (0,1)
Pos: (0,2)
Pos: (1,0)
Pos: (1,1)
Pos: (1,2)
Pos: (2,0)
Pos: (2,1)
Pos: (2,2)

You can control loops by using the break and continue keywords. break exits the loop and continues processing immediately afterward, and continue jumps to the next loop iteration.

Again, many subtle changes have occurred from 2.x to 3.x. Most conditionals and looping work the same, but because we mention it in this section, we should note that print is no longer a statement in 3.x and is now a function call. That provides a nice segue to our discussion of functions.

Functions

Some languages—such as PHP—read and process an entire file before executing it, which means you can call a function before it is defined because the compiler reads the definition of the function before it tries to call it. Python is different: If the function definition has not been reached by the time you try to call it, you get an error. The reason behind this behavior is that Python actually creates an object for your function, and that in turn means two things. First, you can define the same function several times in a script and have the script pick the right one at runtime. Second, you can assign the function to another name just by using =.

A function definition starts with def, then the function name, then parentheses and a list of parameters, and then a colon. The contents of a function need to be indented at least one level beyond the definition. So, using function assignment and dynamic declaration, you can write a script that prints the right greeting in a roundabout manner:

>>> def hello_english(Name):
...     print "Hello, " + Name + "!"
...
>>> def hello_hungarian(Name):
...     print "Szia, " + Name + "!"
...
>>> hello = hello_hungarian
>>> hello("Paul")
Szia, Paul!
>>> hello = hello_english
>>> hello("Paul")

Notice that function definitions include no type information. Functions are typeless, as mentioned previously. The upside of this is that you can write one function to do several things:

>>> def concat(First, Second):
...     return First + Second
...
>>> concat(["python"], ["perl"])
['python', 'perl']
>>> concat("Hello, ", "world!")'Hello, world!'

This example demonstrates how the return statement sends a value back to the caller and also how a function can do one thing with lists and another thing with strings. The magic here is being accomplished by the objects. You write a function that tells two objects to add themselves together, and the objects intrinsically know how to do that. If they do not—if, perhaps, the user passes in a string and an integer—Python catches the error for you. However, it is this hands-off, “let the objects sort themselves out” attitude that makes functions so flexible. The concat() function could conceivably concatenate strings, lists, or zonks—a data type someone created herself that allows adding. The point is that Python does not limit what your function can do. As clichéd as it might sound, the only limit is your imagination.

Object Orientation

After having read this far, you should not be surprised to hear that Python’s object orientation is flexible and likely to surprise you if you have been using C-like languages for some time.

The best way to learn Python object-oriented programming (OOP) is to just do it. Here is a basic script that defines a class, creates an object of that class, and calls a function:

class Dog(object):
    def bark(self):
        print "Woof!"

fluffy = Dog()
fluffy.bark()

Defining a class starts, predictably, with the class keyword followed by the name of the class you are defining and a colon. The contents of that class need to be indented one level so that Python knows where it stops. Note that the object inside parentheses is there for object inheritance, which is discussed later. For now, the least you need to know is that if your new class is not based on an existing class, you should put object inside parentheses, as shown in the previous code.

Functions inside classes work in much the same way as normal functions do (although they are usually called methods); the main difference is that they should all take at least one parameter, usually called self. This parameter is filled with the name of the object the function was called on, and you need to use it explicitly.

Creating an instance of a class is done by assignment. You do not need any new keyword, as in some other languages; providing the parentheses makes the creation known. Calling a function of that object is done using a period and the name of the class to call, with any parameters being passed inside parentheses.

Class and Object Variables

Each object has its own set of functions and variables, and you can manipulate those variables independently of objects of the same type. In addition, a class variable may be set to a default value for all classes, in which case it can be manipulated globally.

This script demonstrates two objects of the dog class being created, each with its own name:

class Dog(object):
     name = "Lassie"
     def bark(self):
         print self.name + " says 'Woof!'"
     def set_name(self, name):
         self.name = name
fluffy = Dog()
fluffy.bark()
poppy = Dog()
poppy.set_name("Poppy")
poppy.bark()

This outputs the following:

Lassie says 'Woof!'
Poppy says 'Woof!'

Here, each dog starts with the name Lassie, but it gets customized. Keep in mind that, by default, Python assigns by reference, meaning each object has a reference to the class’s name variable, and as you assign that with the set_name() method, that reference is lost. This means that any references you do not change can be manipulated globally. Thus, if you change a class’s variable, it also changes in all instances of that class that have not set their own value for that variable. Consider this example:

class Dog(object):
    name = "Lassie"
    color = "brown"
fluffy = Dog()
poppy = Dog()
print fluffy.color
Dog.color = "black"
print poppy.color
fluffy.color = "yellow"
print fluffy.color
print poppy.color

So, the default color of dogs is brown—both the fluffy and poppy Dog objects start off as brown. Then, using Dog.color, you set the default color to be black, and because neither of the two objects has set its own color value, they are updated to be black. The third-to-last line uses poppy.color to set a custom color value for the poppy object: poppy becomes yellow, whereas fluffy and the Dog class in general remain black.

Constructors and Destructors

To help you automate the creation and deletion of objects, you can easily override two default methods: __init__ and __del__. These are the methods that Python calls when a class is being instantiated and freed, known as the constructor and destructor, respectively.

Having a custom constructor is great for when you need to accept a set of parameters for each object being created. For example, you might want each dog to have its own name on creation, and you could implement that with this code:

class Dog(object):
    def __init__(self, name):
        self.name = name
fluffy = Dog("Fluffy")
print fluffy.name

If you do not provide a name parameter when creating the Dog object, Python reports an error and stops. You can, of course, ask for as many constructor parameters as you want, although it is usually better to ask only for the ones you need and have other functions to fill in the rest.

On the other side of things is the destructor method, which enables you to have more control over what happens when an object is destroyed. Using a constructor and destructor, this example shows the life cycle of an object by printing messages when it is created and deleted:

class dog(object):
    def __init__(self, name):
        self.name = name
        print self.name + " is alive!"
    def __del__(self):
        print self.name + " is no more!"
fluffy = Dog("Fluffy")

The destructor is here to give you the chance to free up resources allocated to the object or perhaps log something to a file. Note that although it is possible to override the __del__ method, doing so is very dangerous because it is not guaranteed that __del__ methods are called for objects that still exist when the interpreter exits. The official Python documentation explains this well at https://docs.python.org/reference/datamodel.html#object.__del__.

Class Inheritance

Python allows you to reuse your code by inheriting one class from one or more others. For example, lions, tigers, and bears are all mammals and so share a number of similar properties. In that scenario, you do not want to have to copy and paste functions between them; it is smarter (and easier) to have a mammal class that defines all the shared functionality and then inherit each animal from that.

Consider the following code:

class Car(object):
    color = "black"
    speed = 0
    def accelerate_to(self, speed):
        self.speed = speed
    def set_color(self, color):
        self.color = color
mycar = Car()
print mycar.color

This example creates a Car class with a default color and provides a set_color() function so that people can change their own colors. Now, what do you drive to work? Is it a car? Sure it is, but chances are it is a Ford, or a Dodge, or a Jeep, or some other make; you do not get cars without a make. On the other hand, you do not want to have to define a class Ford and give it the methods accelerate_to(), set_color(), and however many other methods a basic car has and then do the same thing for Ferrari, Nissan, and so on.

The solution is to use inheritance: Define a car class that contains all the shared functions and variables of all the makes and then inherit from that. In Python, you do this by putting the name of the class from which to inherit inside parentheses in the class declaration, like this:

class Car(object):
    color = "black"
    speed = 0
    def accelerate_to(self, speed):
        self.speed = speed
    def set_color(self, color):
        self.color = color
class Ford(Car): pass
class Nissan(Car): pass
mycar = Ford()
print mycar.color

The pass directive is an empty statement; it means the class contains nothing new. However, because the Ford and Nissan classes inherit from the car class, they get color, speed, accelerate_to(), and set_color() provided by their parent class. (Note that you do not need objects after the class names for Ford and Nissan because they are inherited from an existing class: car.)

By default, Python gives you all the methods the parent class has, but you can override that by providing new implementations for the classes that need them. Here is an example:

class Modelt(car):
    def set_color(self, color):
        print "Sorry, Model Ts only come in black!"

myford Ford()
Ford.set_color("green")
mycar = Modelt()
mycar.set_color("green")

The first car is created as a Ford, so set_color() works fine because it uses the method from the car class. However, the second car is created as a Modelt, which has its own set_color() method, so the call fails.

This suggests an interesting scenario: What do you do if you have overridden a method and yet want to call the parent’s method also? If, for example, changing the color of a Model T were allowed but just cost extra, you would want to print a message saying “You owe $50 more” but then change the color. To do this, you need to use the class object from which the current class is inherited (Car in this case). Here’s an example:

class Modelt(Car):
    def set_color(self, color):
        print "You owe $50 more"
        Car.set_color(self, color)

mycar = Modelt()
mycar.set_color("green")
print mycar.color

This prints the message and then changes the color of the car.

The Standard Library and the Python Package Index

A default Python install includes many modules (blocks of code) that enable you to interact with the operating system, open and manipulate files, parse command-line options, perform data hashing and encryption, and much more. This is one of the reasons most commonly cited when people are asked why they like Python so much: It comes stocked to the gills with functionality you can take advantage of immediately. In fact, the number of modules included in the Standard Library is so high that entire books have been written about them.

For unofficial scripts and add-ons for Python, the recommended starting place is called the Python Package Index (pyPI), at https://pypi.python.org/pypi. There you can find more than 10,000 public scripts and code examples for everything from mathematics to games.

References

www.python.orgThe Python website is packed with information and updated regularly. This should be your first stop, if only to read the latest Python news.

www.jython.orgPython also has an excellent Java-based interpreter to allow it to run on other platforms.

www.ironpython.comIf you prefer Microsoft .NET, check out this site.

www.montypython.comGuido van Rossum borrowed the name for his language from Monty Python’s Flying Circus, and as a result many Python code examples use oblique Monty Python references (spam and eggs are quite common, for example). A visit to the official Monty Python site to hone your Python knowledge is highly recommended.

www.zope.orgThis is the home page of the Zope content management system (CMS). One of the most popular CMSs around, Zope is written entirely in Python.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.118.142.166