comment

You mark a comment by using the # character; everything from that point on to the end of the current line is part of the comment.

Python does not have a multiline comment.

However, if it’s in a text string, the all-powerful octothorpe reverts back to its role as a plain old # character:

>>> print("No comment: quotes make the # harmless.")

No comment: quotes make the # harmless.

Continue lines with \

Programs are more readable when lines are reasonably short. The recommended (not required) maximum line length is 80 characters.

method of breaking code into multiple lines

Method 1: Using parenthesis

if (number > 5 and

number < 15):

    print "1"

Method 2: Using backslash

if number > 5 and \

number < 15:

    print "1"

Method 3: Using backslash + indent for better readability

if number > 5 and \

number < 15:

    print "1"
If, elif, and else

 

The if and else lines are Python statements that check whether a condition is True.

I used four spaces to indent each subsection. Although you can use any indentation you like, Python expects you to be consistent with code within a section—the lines need to be indented the same amount, lined up on the left. The recommended style, called PEP-8, is to use four spaces. Don’t use tabs, or mix tabs and spaces; it messes up the indent count.

You can have tests within tests, as many levels deep as needed:

>>> furry = True
>>> small = True
>>> if furry:
...     if small:
...         print("It's a cat.")
...     else:
...         print("It's a bear!")
... else:
...     if small:
...         print("It's a skink!")
...     else:
...         print("It's a human. Or a hairless bear.")
...
It's a cat.
True or false

A false value doesn’t necessarily need to explicitly be False. For example, these are all considered False:

boolean       False
null          None
zero integer  0
zero float    0.0
empty string  ''
empty list    []
empty tuple   ()
empty dict    {}
empty set set ()

Anything else is considered True.

Loop ( while )

While is the simplest looping mechanism, note that you need to make the loop end at some point, or else it will loop endless.

>>> count = 1
>>> while count <= 5:
...     print(count)
...     count += 1
...
1 
2 
3 
4
5

Cancel with break

>>> while True:
...     stuff = input("String to capitalize [type q to quit]: ")
...     if stuff == "q":
...         break
...     print(stuff.capitalize())
...
String to capitalize [type q to quit]: test
Test
String to capitalize [type q to quit]: hey, it works
Hey, it works
String to capitalize [type q to quit]: q

Skip ahead with continue

let’s read an integer, print its square if it’s odd, and skip it if it’s even. We even added a few comments. Again, we’ll use q to stop the loop:

>>> while True:
...     value = input("Integer, please [q to quit]: ")
...     if value == 'q': # quit
...         break
...     number = int(value)
...     if number % 2 == 0: # an even number
...         continue
...     print(number, "squared is", number*number)
...
Integer, please [q to quit]: 1
1 squared is 1
Integer, please [q to quit]: 2
Integer, please [q to quit]: 3
3 squared is 9
Integer, please [q to quit]: 4

with else

The else would be run if the while loop completed but the object was not found:

>>> numbers = [1, 3, 5] >>> position = 0
>>> while position < len(numbers):
…         number = numbers[position] …         if number % 2 == 0:
…             print(‘Found even number’, number)
…             break
…         position += 1
else: # break not called
…         print(‘No even number found’)

No even number found

Iterate with for

Iterators in Python make it possible for you to traverse data structures without knowing how large they are or how they are implemented.

E.g. to print all the item in a list:

>>> rabbits = ['Flopsy', 'Mopsy', 'Cottontail', 'Peter']
>>> current = 0
>>> while current < len(rabbits):
...     print(rabbits[current])
... current += 1
...
Flopsy
Mopsy
Cottontail
Peter

A better Pythonic way:

>>> for rabbit in rabbits:
...     print(rabbit)
...
Flopsy
Mopsy
Cottontail
Peter

Python’s iterable objects: strings, tuples, dictionaries, sets, and some other elements.

Note that by default the python will iterate over the keys for dictionary:

 >>> accusation = {'room': 'ballroom', 'weapon': 'lead pipe',
'person': 'Col. Mustard'}
>>> for card in accusation: # or, for card in accusation.keys():
... print(card)
...
room
weapon
person

To iterate over the values rather than the keys, you use the dictionary’s values() function:

>>> for value in accusation.values():
... print(value)
...
ballroom
lead pipe
Col. Mustard

To return both the key and value in a tuple, you can use the items() function:

>>> for item in accusation.items():
... print(item)
...
('room', 'ballroom')
('weapon', 'lead pipe')
('person', 'Col. Mustard')
cancel or skip

same as for, with break or continue.

Similar to while, for has an optional else that checks if the for completed normally.

If break was not called, the else statement is run. This is useful when you want to verify that the previous for loop ran to completion,instead of being stopped early with a break.

 >>> cheeses = []
>>> for cheese in cheeses:
...      print('This shop has some lovely', cheese)
...      break
... else: # no break means no cheese
...      print('This is not much of a cheese shop, is it?')
...
This is not much of a cheese shop, is it?
Iterate in parallel with zip()

To iterate several data structure in parallel:

>>> days = ['Monday', 'Tuesday', 'Wednesday']
>>> fruits = ['banana', 'orange', 'peach']
>>> drinks = ['coffee', 'tea', 'beer']
>>> desserts = ['tiramisu', 'ice cream', 'pie', 'pudding']
>>> for day, fruit, drink, dessert in zip(days, fruits, drinks, desserts):
...     print(day, ": drink", drink, "- eat", fruit, "- enjoy", dessert)
...
Monday : drink coffee - eat banana - enjoy tiramisu
Tuesday : drink tea - eat orange - enjoy ice cream
Wednesday : drink beer - eat peach - enjoy pie

zip() stops when the shortest sequence is done.

You can use zip() to walk through multiple sequences and make tuples from items at the same offsets. Let’s make two tuples of corresponding English and French words:

>>> english = 'Monday', 'Tuesday', 'Wednesday'
>>> french = 'Lundi', 'Mardi', 'Mercredi'

Now, use zip() to pair these tuples. The value returned by zip() is itself not a tuple or list, but an iterable value that can be turned into one:

>>> list( zip(english, french) )
[('Monday', 'Lundi'), ('Tuesday', 'Mardi'), ('Wednesday', 'Mercredi')]

Feed the result of zip() directly to dict() and voilà: a tiny English-French dictionary!

>>> dict( zip(english, french) )
{'Monday': 'Lundi', 'Tuesday': 'Mardi', 'Wednesday': 'Mercredi'}
Iterate over Code Structures with itertools

Itertools contains special-purpose iterator functions. Each returns one item at a time when called within a for … in loop, and remembers its state between calls.

chain()

chain() runs through its arguments as though they were a single iterable:

>>> import itertools
>>> for item in itertools.chain([1, 2], ['a', 'b']):
 ...     print(item)
 ...
 1
 2
 a
 b

cycle()

cycle() is an infinite iterator, cycling through its arguments:

>> import itertools
 >>> for item in itertools.cycle([1, 2]):
 ...     print(item)
 ...
 1
 2
 1
 2
 .

…and so on.

accumulate()

accumulate() calculates accumulated values. By default, it calculates the sum:

>>> import itertools
>>> for item in itertools.accumulate([1, 2, 3, 4]):
 ...     print(item)
 ...
 1
 3
 6
 10

You can provide a function as the second argument to accumulate(), and it will be used instead of addition. The function should take two arguments and return a  single result.
This example calculates an accumulated product:

>>> import itertools
>>> def multiply(a, b):
 ...     return a * b
 ...
>>> for item in itertools.accumulate([1, 2, 3, 4], multiply):
 ...     print(item)
 ...
 1  //1
 2  //1*2
 6  //1*2*3
 24  //1*2*3*4

The itertools module has many more functions, notably some for combinations and permutations that can be time savers when the need arises.

Generate Number sequences with range()

You use range() similar to how to you use slices: range( start, stop, step ). If you omit start, the range begins at 0. The only required value is stop; as with slices, the last value created will be just before stop. The default value of step is 1, but you can go
backward with -1.

Comprehensions

 

List Comprehensions

You could build a list of integers from 1 to 5, one item at a time, like this:

>>> number_list = []
>>> number_list.append(1)
>>> number_list.append(2)
>>> number_list.append(3)
>>> number_list.append(4)
>>> number_list.append(5)
>>> number_list
[1, 2, 3, 4, 5]

Or, you could also use an iterator and the range() function:

>>> number_list = []
>>> for number in range(1, 6):
... number_list.append(number)
...
>>> number_list
[1, 2, 3, 4, 5]

Or, you could just turn the output of range() into a list directly:

>>> number_list = list(range(1, 6))
>>> number_list
[1, 2, 3, 4, 5]
The simplest form of list comprehension is:
[ item for item in iterable ]

 

Note that the two item must be same variable name.

Here’s how a list comprehension would build the integer list:

>>> number_list = [number for number in range(1,6)]
>>> number_list
[1, 2, 3, 4, 5]
Add a condition expression:

[ item for item in iterable if condition ]

Let’s make a new comprehension that builds a list of only the odd numbers between 1 and 5 (remember that number % 2 is True for odd numbers and False for even numbers):

>>> a_list = [number for number in range(1,6) if number % 2 == 1]
>>> a_list
[1, 3, 5]
make a list of tuples:

let’s use a comprehension and assign it to the variable cells, making it a list of (row, col) tuples:

>>> rows = range(1,4)
>>> cols = range(1,3)
>>> cells = [(row, col) for row in rows for col in cols]
>>> for cell in cells:
... print(cell)
...
(1, 1)
(1, 2)
(2, 1)
(2, 2)
(3, 1)
(3, 2)
Dictionary comprehensions

The simplest form looks familiar:

{ key_expression : value_expression for key_expression in iterable }

Similar to list comprehensions, dictionary comprehensions can also have if tests and multiple for clauses:

>>> word = 'letters'
>>> letter_counts = {letter: word.count(letter) for letter in word}
 >>> letter_counts
{'l': 1, 'e': 2, 't': 2, 'r': 1, 's': 1}

We are running a loop over each of the seven letters in the string ‘letters’ and counting how many times that letter appears.

Performance consideration:

Two of our uses of word.count(letter) are a waste of time because we have to count all the e’s twice and all the t’s twice. But, when we count the e’s the second time, we do no harm because we just replace the entry in the dictionary that was already there; the same goes for counting the t’s. So, the following would have been a teeny bit more Pythonic:

>>> word = 'letters'
>>> letter_counts = {letter: word.count(letter) for letter in set(word)}
>>> letter_counts
{'t': 2, 'l': 1, 'e': 2, 'r': 1, 's': 1}

The dictionary’s keys are in a different order than the previous example, because iterating set(word) returns letters in a different order than iterating the string word.

Set comprehensions

The simplest version looks like the list and dictionary comprehensions that you’ve just seen:

{ expression for expression in iterable }

The longer versions (if tests, multiple for clauses) are also valid for sets:

>>> a_set = {number for number in range(1,6) if number % 3 == 1}
>>> a_set
{1, 4}

Tuples ?? Tuples do not have comprehensions!!!
But it would appear to work because there’s no exception if you type this:

>>> number_thing = (number for number in range(1, 6))

The thing between the parentheses is a generator comprehension, and it returns a generator object:

>>> type(number_thing)
<class 'generator'>

I’ll get into generators in the later part of this chapter.