Chapter 5 conditions, loops and other statements

Keywords: Python

  • Explore conditional statements and loop statements in depth.
  • Introduce list derivation. Although they are expressions, they work almost the same as conditional statements and loop statements.
  • Finally, pass, del and exec are introduced.

5.1 talk about print and import again

5.1.1 printing multiple parameters

# 1) Multiple expressions can be printed at the same time, separated by commas:
>>> print('Age:', 42) 
Age: 42
# A space character was inserted between the parameters.
>>> name = 'Gumby'
>>> salutation = 'Mr.'
>>> greeting = 'Hello,'
>>> print(greeting, salutation, name) 
Hello, Mr. Gumby
# 2) If string variable greeting does not contain a comma, how do you add it to result?
# Add the comma and the variable greeting
print(greeting + ',', salutation, name)
# 3) Customizable separator
>>> print("I", "wish", "to", "register", "a", "complaint", sep="_")
I_wish_to_register_a_complaint
# 4) You can customize the end string to replace the default line break. For example, if you specify the end string as an empty string, you can continue printing to the current line later.
>>>print('Hello,', end='') 
>>>print('world!')
# Print the above code Hello, world! 

5.1.2 rename during import

# When importing from a module, you usually use
import somemodule
from somemodule import somefunction
from somemodule import somefunction, anotherfunction, yetanotherfunction
from somemodule import *
# The last method is used when you decide to import everything in the module.
# If both modules contain the function open, you can import the two modules in the first way and call the function as follows:
module1.open(...) 
module2.open(...)
# Another way: add an as clause at the end of the statement and specify an alias. An example of importing an entire module and specifying an alias:
>>> import math as foobar 
>>> foobar.sqrt(4)
2.0
# Examples of importing specific functions and specifying aliases:
>>> from math import sqrt as foobar
>>> foobar(4) 
2.0
# For the previous open functions, you can import them as follows:
from module1 import open as open1
from module2 import open as open2

5.2 assignment magic

5.2.1 sequence unpacking

# 1) Assign values to variables;
# 2) Assign values to a part of a data structure, such as elements and slices in a list, or dictionary items;
# 3) There are other types of assignment statements. For example, multiple variables can be assigned simultaneously (in parallel);
>>> x, y, z = 1, 2, 3 
>>> print(x, y, z) 
123
# In this way, you can also exchange the values of multiple variables.
>>> x, y = y, x 
>>> print(x, y, z) 
213
# This operation is called sequence unpacking (or iterative object unpacking): unpack a sequence (or any iterative object) and store the resulting value in a series of variables.
>>> values = 1, 2, 3 
>>> values
(1, 2, 3)
>>> x, y, z = values 
# This is useful when using functions or methods that return tuples (or other sequences or iteratable objects). Assuming that you want to arbitrarily obtain (or delete) a key value pair from the dictionary, you can use the method popitem, which arbitrarily obtains a key value pair and returns it as a tuple. The returned tuple can be unpacked directly into two variables.
>>> scoundrel = {'name': 'Robin', 'girlfriend': 'Marion'} 
>>> key, value = scoundrel.popitem()
# The sequence to be unpacked must contain the same number of elements as the target number listed on the left of the equal sign, otherwise an exception will be thrown.
# The asterisk operator (*) can be used to collect redundant values, so it is not necessary to ensure that the number of hedges and variables are the same:
 >>> a, b, *rest = [1, 2, 3, 4] 
 >>> rest
[3, 4]
# Variables with asterisks can also be placed in other locations.
>>> name = "Albus Percival Wulfric Brian Dumbledore" 
>>> first, *middle, last = name.split()
>>> middle
['Percival', 'Wulfric', 'Brian']
# The right side of the assignment statement can be any type of sequence, but the variables with asterisks always contain a list. This is also true when the number of variables and values is the same.
>>> a, *b, c = "abc"
>>> a, b, c
('a', ['b'], 'c')
# This collection method can also be used in the function parameter list

5.2.2 chain assignment

Chained assignment is a shortcut for associating multiple variables to the same value:

x = y = somefunction()
# The above code is equivalent to the following code:
y = somefunction() 
x=y
# Note that these two statements may not be equivalent to the following statements: 
x = somefunction()
y = somefunction()
# For details on this, see section 5.4.6 on the same operator (is).

5.2.3 enhanced assignment

# You can write x += 1 instead of x = x + 1. This is called enhanced assignment and applies to all standard operators such as *, /,%, etc.
>>> x = 2 
>>> x += 1
>>> x *= 2 
>>> x
6
# Enhanced assignment can also be used for other data types (as long as the binocular operator used can be used for these data types).
>>> fnord = 'foo' 
>>> fnord += 'bar' 
>>> fnord *= 2
>>> fnord 
'foobarfoobar'
# By using enhanced assignment, you can make the code more compact, concise, and more readable in many cases.

5.3 code blocks: fun of indentation

A code block is a set of statements that can be executed when conditions are met (if statements), multiple times (loops), and so on. Code blocks are created by indenting code (that is, preceded by spaces). In the same code block, the indent of each line of code must be the same.

5.4 conditions and conditional statements

5.4.1 this is where Boolean values come in

When used as a Boolean expression, such as a condition in an if statement, the following values are treated as False by the interpreter: False None 0 "" () [] {}. Although there are many truth values to choose from, the standard truth values are True and False.
In some languages, such as C and Python before 2.3, the standard True values are 0 (for False) and 1 (for True). In fact, True and False are just aliases of 0 and 1. Although they look different, they have the same effect.

>>> True == 1 11 
True
>>> False == 0
True
>>> True + False + 42 
43
# Boolean values True and False are of type bool, which, like list, str and tuple, can be used to convert other values.
>>> bool('I think, therefore I am') 
True
>>> bool(42)
True
>>> bool('') 
False
>>> bool(0) 
False

5.4.2 conditionally execute and if statements

name = input('What is your name? ') 
if name.endswith('Gumby'):
	print('Hello, Mr. Gumby')
# Execute code conditionally. If the condition is true, subsequent code blocks are executed; If the condition is false, it will not be executed.

5.4.3 else clause

# You can use the else clause to add a choice (it is called a clause because else is not a separate statement, but part of an if statement).
name = input('What is your name?') 
if name.endswith('Gumby'):
	print('Hello, Mr. Gumby') 
else:
	print('Hello, stranger')
# If the first code block is not executed (because the condition is false), the second code block is entered

# There is also a "relative" similar to the if statement, which is the conditional expression, the Python version of the ternary operator in C language. The following expression uses if and else to determine its value:
status = "friend" if name.endswith("Gumby") else "stranger" 
# If the condition is true, the result of the expression is the first value provided, otherwise it is the second value.

5.4.4 elif clause

# To check multiple conditions, use elif. Elif is the abbreviation of else if. It is composed of an if clause and an else clause, that is, an else clause containing conditions.
num = int(input('Enter a number: ')) 
if num > 0:
	print('The number is positive') 
elif num < 0:
	print('The number is negative') 
else:
	print('The number is zero')

5.4.5 code block nesting

Here's something extra. Can be if Statement in other if Statement block, as shown below:
name = input('What is your name? ') 
if name.endswith('Gumby'):
	if name.startswith('Mr.'): 
		print('Hello, Mr. Gumby') 
	elif name.startswith('Mrs.'):
		print('Hello, Mrs. Gumby') 
	else:
		print('Hello, Gumby') 
else:
	print('Hello, stranger')

5.4.6 more complex conditions

  1. Comparison operator
    In conditional expressions, the most basic operators may be comparison operators, which are used to perform comparisons. Table 5-1 summarizes the comparison operators.

    Like assignment, Python also supports chained comparison: multiple comparison operators can be used at the same time, such as 0 < age < 100.
    Some comparison operators need special attention, which will be described in detail below.
# 1) To determine whether two objects are equal, you can use a comparison operator, represented by two equal signs (= =).
>>> "foo" == "foo" 
True
>>> "foo" == "bar" 
False
# 2)is: the same operator. This operator is very interesting. It seems to work the same as = =, but it is not.
>>> x=y=[1,2,3]
>>> z=[1,2,3]
>>> x is y
True
>>> x is z
False
>>> x==y
True
>>> x==z
True
# is checks whether two objects are the same (not equal). Variables x and y point to the same list, while z points to another list (the values contained in it and the order in which they are arranged are the same as the previous list). Although the two lists are equal, they are not the same object.

# 3)in: membership operator. Like other comparison operators, it can also be used in conditional expressions
name = input('What is your name?') 
if 's' in name:pass

# 4) Comparison of strings and sequences. Strings are compared according to the alphabetical order of characters.
>>> "alpha" < "beta" 
True
# Although it is based on alphabetical order, the letters are Unicode characters, which are arranged by code points.
>>> "🐡🐡" < "🐢🐢"
# In fact, characters are arranged according to sequential values. To learn the alphabetical values, use the function ord. This function is the opposite of chr:
>>> ord("🐡") 
128585
>>> ord("🐢") 
128586
>>> chr(128584) 
>'🐱'
# This method is reasonable and consistent, but it may be the opposite of the way you sort.
# When it comes to capital letters, the order may be different from what you want.
>>> "a" < "B" 
False
# One trick is to ignore case:
>>> "a".lower() < "B".lower()
True
# Other sequences are compared the same way, but these sequences may contain elements that are not characters, but other types of values.
>>> [1, 2] < [2, 1] 
True
# If the elements of a sequence are other sequences, they are compared according to the same rules.
>>> [2, [1, 4]] < [2, [1, 5]] 
True
  1. Boolean operator
    You may need to check several conditions:
number = int(input('Enter a number between 1 and 10: ')) 
if number <= 10 and number >= 1:
	print('Great!') 4 
else:
	print('Wrong!')

# The operator and is a Boolean operator. It accepts two truth values. There are two other Boolean operators: or and not. By using these three operators, you can combine truth values in any way.
if ((cash > price) or customer_has_good_credit) and not out_of_stock:
	give_goods()

5.4.7 assertion

The if statement has a useful "relative", and its working principle is similar to the following pseudo code:
if not condition:
crash program
Why write code like this? Because it is better to let the program crash immediately when the error condition occurs than later. You can require certain conditions to be met (such as verifying that the function parameters meet the requirements or providing help for initial testing and debugging). For this purpose, you can use the keyword assert in the statement.

>>> age = 10
>>> assert 0 < age < 100
>>> age = -1
>>> assert 0 < age < 100
Traceback (most recent call last):
File "<stdin>", line 1, in ? AssertionError
# If you know that certain conditions must be met for the program to run correctly, it is helpful to add an assert statement to the program as a checkpoint.
# You can also add a string after the condition to describe the assertion.
>>> age = -1
>>> assert 0 < age < 100, 'The age must be realistic' Traceback (most recent call last):
File "<stdin>", line 1, in ? AssertionError: The age must be realistic

5.5 cycle

You may want to create a program to remind you to pay rent every month
while we aren't stopped:
send mail
wait one month

5.5.1 while loop

x=1
while x <= 100:
	print(x) 
	x += 1

5.5.2 for cycle

The while statement is very flexible and can be used to repeatedly execute code blocks when the condition is true. This is usually good, but sometimes you may want to customize it as needed.
One requirement is to execute a block of code for each element in a sequence (or other iteratable object).

# To do this, use the for statement:
words = ['this', 'is', 'an', 'ex', 'parrot']
for word in words:
	print(word)
# Since it is a common task to iterate over a number within a specific range, Python provides a built-in function to create a range.
>>> range(0, 10)
range(0, 10)
>>> list(range(0, 10))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
# They contain the start position (0 here) but not the end position (10 here)
# If only one position is provided, this position will be regarded as the end position and the starting position is assumed to be 0.
>>> range(10) 
range(0, 10)

# The following program prints 1 ~ 100, which is much more compact than the while loop used earlier.
for number in range(1,101):
	print(number)

5.5.3 iteration dictionary

# To traverse all the keywords of the dictionary, you can use a normal for statement like a traversal sequence.
d = {'x': 1, 'y': 2, 'z': 3} 
for key in d:
	print(key, 'corresponds to', d[key])
# You can also use dictionary methods such as keys to get all the keys. Or use d.values. d.items returns key value pairs as tuples. One of the advantages of the for loop is that sequence unpacking can be used in it.
for key, value in d.items():
	print(key, 'corresponds to', value)

5.5.4 some iteration tools

Python provides several functions to help iterate sequences (or other iteratable objects), some of which are located in the module itertools introduced in Chapter 10, but some built-in functions are also convenient to use.

# 1. Parallel iteration, iterating two sequences at the same time
names = ['anne', 'beth', 'george', 'damon'] 
ages = [12, 45, 32, 102]
# If you want to print the name and corresponding age, you can do the following:
for i in range(len(names)):
	print(names[i], 'is', ages[i], 'years old')
# The parallel iteration tool has a built-in function zip, which "stitches" the two sequences and returns a sequence composed of tuples. The return value is an object suitable for iteration. To view its contents, use list to convert it into a list.
>>> list(zip(names, ages))
[('anne', 12), ('beth', 45), ('george', 32), ('damon', 102)]
# After "stitching", tuples can be unpacked in a loop.
for name, age in zip(names, ages): 
	print(name, 'is', age, 'years old')

# 2. Get index during iteration
# TODO

# 3. Reverse iteration and iteration after sorting 
# reversed and sorted. They are similar to the list methods reverse and sort (the parameters accepted by sorted are also similar to sort), but they can be used for any sequence or iteratable object. Instead of modifying the object in place, they return the inverted and sorted version.
>>> sorted([4, 3, 6, 8, 3])
[3, 3, 4, 6, 8]
>>> sorted('Hello, world!')
[' ', '!', ',', 'H', 'd', 'e', 'l', 'l', 'l', 'o', 'o', 'r', 'w'] 
>>> list(reversed('Hello, world!'))
['!', 'd', 'l', 'r', 'o', 'w', ' ', ',', 'o', 'l', 'l', 'e', 'H'] 
>>> ''.join(reversed('Hello, world!'))
'!dlrow ,olleH'
# sorted returns a list, while reversed returns a more mysterious iteratable object like zip.
# You don't have to worry about what this means. Just use it in methods such as a for loop or join. It's just that you can't index or slice it, and you can't call list methods directly on it.
# To perform these operations, first convert the returned object using list.

# To sort alphabetically, first convert to lowercase. To do this, set the key parameter of sort or sorted to str.lower. For example, sorted("aBc", key=str.lower) returns ['a ',' B ',' C '].

5.5.5 jump out of cycle

Usually, a loop will continue to execute the code block until the condition is false or all elements in the sequence are used. However, in some cases, you may want to break the loop, start a new iteration (enter the "next round" code block execution process), or end the loop directly.

  1. break
    To end (jump out) the loop, use break. Suppose you want to find the maximum square value less than 100, you can iterate down from 100. After finding a square value, there is no need to iterate again, so you can jump out of the loop directly.
from math import sqrt
for n in range(99, 0, -1):
	root = sqrt(n)
	if root == int(root):
		print(n)
		break
  1. continue
    It ends the current iteration and jumps to the beginning of the next iteration. It skips the remaining statements in the loop body, but does not end the loop. This is useful when the loop body is large and complex and there are multiple reasons to skip it. In this case, you can use continue, as follows:
for x in seq:
	if condition1: continue 
	if condition2: continue 
	if condition3: continue
	do_something() 
	do_something_else() 
	do_another_thing() etc()
# However, in many cases, an if statement is sufficient.
for x in seq:
	if not (condition1 or condition2 or condition3):
		do_something() 
		do_something_else() 
		do_another_thing() etc()
  1. while True/break example
# Suppose you want to do something when the user enters a word according to the prompt, and end the loop when the user does not provide a word
word = 'dummy'
while word:
	word = input('Please enter a word: ') 
	print('The word was', word)
# In order to enter the loop, you need to assign a dummy value (unused value) to word. A dummy value like this usually indicates that you are not doing right. Let's try to eliminate this dummy value.
word = input('Please enter a word: ') 
while word:
	print('The word was', word)
	word = input('Please enter a word: ') 
# Dummy values are eliminated, but contain duplicate code (which is not good): you need to use the same assignment statement in two places and call input. How to avoid such duplication? You can use the example while True/break.
while True:
	word = input('Please enter a word: ') 
	if not word: 
		break
	# Use this word to do something:
	print('The word was ', word)

5.5.6 else clause in loop

It is easy to take some action at the early end of the cycle, but sometimes you may want to take some action at the normal end of the cycle.
Add an else clause to the loop, which is executed only when break is not called. Continue with the example when break was discussed earlier.

from math import sqrt
for n in range(99, 81, -1):
	root = sqrt(n)
	if root == int(root):
		print(n)
		break
else:
	print("Didn't find it!")

5.6 simple derivation

List derivation is a way to create lists from other lists, similar to set derivation in mathematics. The working principle of list derivation is very simple, which is a bit similar to the for loop.

>>> [x * x for x in range(10)] 
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
# If you want to print only those square values that can be divided by 3
>>> [x*x for x in range(10) if x%3 == 0]
[0, 9, 36, 81]
# You can also add more for sections.
>>> [(x,y) for x in range(0,3) for y in range(0,3)]
[(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]
# In contrast, the following two for loops create the same list:
result = []
for x in range(3):
	for y in range(3) 
		result.append((x, y))
# if clauses can also be added when multiple for parts are used.
>>> girls = ['alice', 'bernice', 'clarice']
>>> boys = ['chris', 'arnold', 'bob']
>>> [b+'+'+g for b in boys for g in girls if b[0] == g[0]] ['chris+clarice', 'arnold+alice', 'bob+bernice']

TODO

5.7 three person bank

Three other statements: pass, del, and exec.

5.7.1 do nothing

# Sometimes you don't have to do anything
>>> pass 
>>>
# Use it as a placeholder when writing code

5.7.2 delete using del

Python usually deletes objects that you no longer use (because no variables or data structure members point to it).

>>> scoundrel = {'age': 42, 'first name': 'Robin', 'last name': 'of Locksley'} 
>>> robin = scoundrel
>>> scoundrel
{'age': 42, 'first name': 'Robin', 'last name': 'of Locksley'}
>>> robin
{'age': 42, 'first name': 'Robin', 'last name': 'of Locksley'} >>> scoundrel = None
>>> robin
{'age': 42, 'first name': 'Robin', 'last name': 'of Locksley'} >>> robin = None
# Initially, robin and scorel point to the same dictionary, so after assigning None to scorel, you can still access the dictionary through robin.
# However, when robin is also set to None, the dictionary floats in the computer memory without any name associated with it, and it can no longer be obtained or used.
# Therefore, the Python interpreter deletes it directly. This is called garbage collection. Note that in the previous code, you can also assign any other value (instead of None) to the two variables, so the dictionary will disappear.

# Another way is to use the del statement. (Chapters 2 and 4 used this statement to delete sequences and dictionaries, remember?) this will delete not only the reference to the object, but also the name itself.
>>> x = 1
>>> del x
>>> x
Traceback (most recent call last):
File "<pyshell#255>", line 1, in ? x
NameError: name 'x' is not defined

>>> x = ["Hello", "world"] >>> y = x
>>> y[1] = "Python"
>>> x
['Hello', 'Python']
# You may think that by deleting x, you will also delete y, but this is not the case.
>>> del x
>>> y
['Hello', 'Python']
# Because X and Y point to the same list, but deleting X has no effect on y, because you only delete the name x, not the list itself (value). In fact, in Python, there is no way to delete values, and you don't need to do so, because the Python interpreter will delete values you no longer use immediately.

5.7.3 using exec and eval to execute strings and calculate the results

TODO

Posted by ignace on Fri, 12 Nov 2021 05:57:39 -0800