Python 3 quick start 2 - process control and functions

Keywords: Python Deep Learning

This article assumes that you already have a foundation of object-oriented programming language, such as Java, and want to quickly understand and use Python language. This paper describes the key syntax, data structure and usage in detail, and illustrates some difficult points for you to get started quickly. Some biased knowledge points will be queried according to the actual needs after you get started Official documents You can. Don't grasp your beard and eyebrows when learning. At the same time, be sure to follow the example and write more handwritten code. When learning a new language, it is recommended that you brush leetcode at the same time, which can not only quickly familiarize yourself with the use of the new language, but also lay a foundation for finding a job in the future. It is recommended to brush leetcode directly on the web page, because you are usually asked to write code directly on the web page during the interview. Leetcode can brush the question path in the way I recommend. In the following code, the lines beginning with > > > and... Are the code part in interactive mode, >? The first line is the input in interactive mode, and the other lines are the output. Use # open line comments in python code.

Programming appetizer

>>> a, b = 0, 1
... while a < 10:
...    print(a, end=', ')
...    a, b = b, a+b     # Multiple assignment, the right expression has been evaluated before assignment
...    
0, 1, 1, 2, 3, 5, 8,     # Fibonacci series

The above is a typical python code block, and the code lines in python do not need to be written in; At the end, the control block begins and ends with indents. The comparison operators in python are similar to those in C and Java. It should be noted that: = = compare whether the values of the objects referred to by the two references are the same. To compare whether the two references point to the same object, you need to use the is keyword. You can also check whether the IDs of the objects referred to by the two references are the same through the id method.

>>> a = [1, 2, 3]
... b = [1, 2, 3]
... print('a = b:', a == b)
a = b: True          # a. The number of elements in B is the same and the values are equal in turn

>>> a is b
False				 # a. B does not point to the same object

>>> c = a
>>> c is a			 # a. C points to the same object
True
>>> id(c)
2827535985280
>>> id(a)
2827535985280		 # c. A refers to the same object id, so it points to the same object

Process control

if statement

If statements in Python include if, elif, and else clauses. Elif is equivalent to else if in C or Java

>>> x = int(input("input a digit: "))
... if a < 0:
...     print("Negative")
... elif a == 0:
...     print("Zero")
... else:
...     print("Positive")
...
input a digit: >? 10
Positive

for and while statements

The for statement in Python is usually used to traverse containers such as lists and strings. It cannot control the number of for loops by adding conditional judgment and variable increment rules in the for statement as in C and Java:

>>> digits = [1, 2, 3]
... for x in digits:        # Traversal list
...     print(x, end=", ")
...     
1, 2, 3, 

>>> s = "python"
... for ch in s:            # Traversal string
...     print(ch, end=" ")
...     
p y t h o n 

Due to this "defect" of the for statement in Python, how can we facilitate the subscript to traverse the list in the for statement like C and Java? First, we can use the while loop:

# Traverse the list according to the subscript in while
>>> digits = [1, 2, 3]
>>> i = 0
... while i < len(digits):
...     print(digits[i], end=" ")
...     i = i + 1
...     
1 2 3 

# Modify the list according to the subscript in while
>>> digits = [1, 2, 3]
>>> i = 0
... while i < len(digits):
...     if digits[i] == 2:
...         digits[i] = 8
...     i = i + 1
...     
>>> print(digits)
[1, 8, 3]

Secondly, we can also use range() Function sum enumerate() Function:

# Use range to create a subscript sequence in steps of 1 with 0 as the starting point, len as the end point (not included)
>>> digits = [1, 2, 3]
... for i in range(len(digits)):
...     print(digits[i], end=" ")
...     
1 2 3 

>>> digits = [1, 2, 3]
... for i in range(len(digits)):
...     if digits[i] == 2:
...         digits[i] = 8
... print(digits)
[1, 8, 3]

# Using enumerate to create an enumeration sequence, you can get the location index and the corresponding value at the same time
>>> digits = [1, 2, 3]
... for i, v in enumerate(digits):
...     print(i, v)
...     
0 1
1 2
2 3

>>> digits = [1, 2, 3]
... for i, v in enumerate(digits):
...     if v == 2:
...         digits[i] = 8
... print(digits)
[1, 8, 3]

We can also use the for statement to traverse the dictionary:

# Traverse the key of the dictionary object
>>> cities = {"chengdu": "A", "mianyang": "B", "guangyuan": "H"}
... for k in cities:
...     print(k, end=" ")
...     
chengdu mianyang guangyuan 

# When traversing the dictionary object, it also traverses the value according to the key
>>> cities = {"chengdu": "A", "mianyang": "B", "guangyuan": "H"}
... for k in cities:
...     print(k, cities[k], sep=": ")
...     
chengdu: A
mianyang: B
guangyuan: H

# After calling the items method of the dictionary object, you can traverse key and value at the same time
>>> cities = {"chengdu": "A", "mianyang": "B", "guangyuan": "H"}
... for k, v in cities.items():
...     print(k, v, sep=": ")
...     
chengdu: A
mianyang: B
guangyuan: H

Note: in the for statement, the declared variable still exists after the loop ends, while the list, tuple and other derived expressions will not:

>>> for x in [1, 2, 3]:
...     print(x)
...     
1
2
3
>>> print(x)
3

It is generally not recommended to directly modify the original data set to obtain the data set we want when traversing the data set, which is unsafe and inflexible. It is recommended to create a new data set according to conditions when traversing the original data set, which is the strength of the for statement in Python language.

List derivation

List derivation creates a list. The square brackets of the list derivation include: an expression, followed by a for clause, and then zero or more for or if clauses.

# Create a square list of 0 - 9
>>> [v**2 for v in range(10)]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

# Verify whether the variables in the for clause still exist after the list derivation is executed
>>> [v**2 for v in range(10)]
... print(v)
Traceback (most recent call last):
  File "<input>", line 2, in <module>
NameError: name 'v' is not defined

# Combine unequal elements in two lists
>>> [(x, y) for x in [1, 2, 3] for y in [1, 2, 3] if x != y]
[(1, 2), (1, 3), (2, 1), (2, 3), (3, 1), (3, 2)]
# Equivalent to
>>> res = []
... for x in [1, 2, 3]:
...     for y in [1, 2, 3]:
...         if x != y:
...             res.append((x, y))
... print(res)
[(1, 2), (1, 3), (2, 1), (2, 3), (3, 1), (3, 2)]

The first expression of the list derivation can be not only a complex expression, function, but also another list derivation:

>>> matrix = [
...     [1, 2, 3],
...     [4, 5, 6],
...     [7, 8, 9]
... ]
... 
# Create transpose of matrix
>>> [[row[i] for row in matrix] for i in range(3)]
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]
# Equivalent to
>>> res = []
... for i in range(3):
...     res.append([row[i] for row in matrix])
... print(res)
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]
# Equivalent to
>>> res = []
... for i in range(3):
...     temp = []
...     for row in matrix:
...         temp.append(row[i])
...     res.append(temp)
... print(res)
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]

Similar to lists, collections and dictionaries also support derivation (tuples do not support):

# Set derivation
>>> { x**2 for x in [1, 2, 1, 4]}
{16, 1, 4}

# Dictionary derivation
>>> { x: x**2 for x in [1, 2, 1, 4]}
{1: 1, 2: 4, 4: 16}

break, continue, and else statements in a loop

The loop in Python also supports break and continue statements in other languages. In addition, it also provides an else statement: in the for loop, when all the elements in the iteratable object are cycled, or when the condition of the while loop is false, this clause is executed; The clause is not executed when the break statement terminates a loop.

# The else clause is executed when all the elements in the iteratable object are cycled
>>> for x in []:
...     print(x, end=" ")
... else:
...     print("end")
...     
end

>>> for x in range(3):
...     print(x, end=" ")
... else:
...     print("end")
...     
0 1 2 end

# If you use a break statement to terminate a loop, the else clause is not executed
>>> for x in range(3):
...     print(x, end=" ")
...     if x == 2:
...         break
... else:
...     print("end")
...     
0 1 2

# continue does not affect the of the else clause
>>> for x in range(3):
...     print(x, end=" ")
...     if x == 2:
...         continue
... else:
...     print("end")
...     
0 1 2 end

# Execute else clause when the while condition is false
>>> x = 10
... while x < 10:
...     print(x)
... else:
...     print("not in while")
...     
not in while

match statement (supported from 3.10)

The match statement is similar to the switch statement in other languages. It is often used to replace multiple if statements:

>>> status = 404
... match status:
...     case 404:  # By default, only one branch is matched, and break statements in other languages are not required and cannot be added
...         print("Not Found!")
...     case 500:
...         print("Internal Error!")
...     case _:    # _  Similar to default in other languages
...         print("Not Known!")
...         
Not Found!

When we want multiple case s to match the same result, we can use |:

case 401 | 402 | 403:
    print("Not Allowed!")

match is powerful in that it can extract sub parts (sequence elements or object attributes) from values and assign them to variables:

>>> point = (1, 2)
... match point:
...     case (0, 0):
...         print("Origin")
...     case (0, y):
...         print("on Y axis, y =", y)
...     case (x, 0):
...         print("on X axis, x =", x)
...     case (x, y):
...         print("x =", x, "y =", y)
...     case _:
...         print("Not Valid!")
...         
x = 1 y = 2

When more functions are needed, you can query the document: match statement.

Python also supports pass Statement that does nothing. You can use a statement when the syntax requires it, but the program does not actually perform any action. This statement can be used as a placeholder for function or conditional clauses to allow developers to focus on more abstract levels.

function

You must know something about functions. Compared with other languages, functions in Python support richer ways of passing parameters. Function definition starts with def keyword:

>>> def printFib(n):
...     """Print Fibonacci series
...     
...     :param n: less than n
...     :return: None
...     """
...     a, b = 0, 1
...     
...     while a < n:
...         print(a, end=" ")
...         a, b = b, a + b
...
>>> printFib(10)
0 1 1 2 3 5 8
>>> print(printFib(10))
0 1 1 2 3 5 8 
None  # Default return value

# Through the help function or function__ doc__ Variable to view the contents of the document
>>> help(printFib)
Help on function printFib in module __main__:

printFib(n)
    Print Fibonacci series
    
    :param n: less than n
    :return: None

>>> print(printFib.__doc__)
Print Fibonacci series
    
    :param n: less than n
    :return: None

In the appeal code block, "..." "" represents the document string, which is used to describe the function purpose, function parameters and return values. Using the document string can automatically generate online documents or printed documents. It is a good habit to add the document string to the code. See Document string . When defining the printFib function, the return statement is not called to display the return value, but it will still return None by default.

Parameter defaults

When defining a function, we can specify default values for parameters at the same time. The parameters with default values are optional when calling:

>>> def area(length, width = None):
...     """Calculate rectangular area
...     
...     :param length: long
...     :param width: Width, default to Noneļ¼›If omitted, calculate with length Square area with side length
...     :return: Rectangular area
...     """
...     if width is None:
...         width = length
...     return length * width
... 
>>> print(area(4, 3))
12
>>> print(area(4))
16

Note: the default value of the formal parameter is calculated only once when the function is defined. If the default value of the parameter is a variable type, multiple calls to the function may affect each other. For example, the following function accumulates the parameters passed in subsequent calls:

>>> def f(a, l=[]):
...     l.append(a)
...     return l
... 
>>> print(f(1))
[1]
>>> print(f(2))
[1, 2]

# The following methods are recommended
>>> def f(a, l=None):
...     if l is None:
...         l = []
...     l.append(a)
...     return l
... 
>>> print(f(1))
[1]
>>> print(f(2))
[2]

Keyword parameters

By default, when calling functions in Python, the parameters can be passed in to the parameters according to the position and order of the function definition, and the parameters can be passed in the way of keywords (formal parameter = formal parameter).

# Or use the area function of the previous section (parameter default value)
# Keyword parameter transfer, not in defined order
>>> print(area(width=2, length=4))
8

# Mixed use of location parameter and keyword parameter
>>> print(area(8, width=4))
32

# An error is reported when the keyword parameter is transferred before the location parameter is transferred
>>> print(area(length=1, 2))
  File "<input>", line 1
    print(area(length=1, 2))
                          ^
SyntaxError: positional argument follows keyword argument

Variable parameters

When we define a function and are not sure how many parameters will be passed in when calling the function, we can use variable parameters to match. The variable parameters start with * and the matching results are stored in the form of tuples. For example, calculate the sum or product of multiple numbers:

>>> def calc(base, *args, operation="+"):
...     match operation:
...         case "+":
...             for i in args:
...                 base += i
...             return base
...         case "*":
...             for i in args:
...                 base *= i
...             return base
...         case _:
...             return "error"
...
# When transferring parameters, 10 matches the base; 1, 2 and 3 match to variable parameter args; operation is the default,
# If you want to override the default value of operation, you must use the keyword to pass the parameter, otherwise it will be matched to the variable parameter
>>> print(calc(10, 1, 2, 3))
16

# When transferring parameters, 10 matches the base; 1, 2 and 3 are matched to variable parameters; The operation parameter passed through the keyword is changed to*
>>> print(calc(1, 1, 2, 3, operation="*"))
6

# Keyword parameters cannot precede positional parameters
>>> print(calc(base = 0, 1, 2, 3))
  File "<input>", line 1
    print(calc(base = 0, 1, 2, 3))
                                ^
SyntaxError: positional argument follows keyword argument

Keyword parameters

Through the previous explanation, we already know that parameters can be passed through keywords when calling functions. When the keyword parameters we pass cannot be exactly matched by the formal parameters defined in the function, we can obtain the remaining unmatched variables through the keyword parameters. The keyword parameters start with * * and the matching results are stored in the dictionary.

>>> def calc(base, *args, operation="+", **others):
...     if len(others) > 0:
...         print("invalid: more keyword arguments:", others)
...         return None
...     match operation:
...         case "+":
...             for i in args:
...                 base += i
...             return base
...         case "*":
...             for i in args:
...                 base *= i
...             return base
...         case _:
...             return "error"
...

>>> print(calc(1, 1, 2, 3, operation="*"))
6

>>> print(calc(1, 1, 2, 3, operation="*", otherOne = 12, otherTwo = 13))
invalid: more keyword arguments: {'otherOne': 12, 'otherTwo': 13}
None

Tip: the location parameter must precede the keyword parameter. It's easy to understand, because as mentioned earlier: the location parameter must be passed before the keyword parameter.

Special parameters / and*

By default, when calling functions in Python, the parameters can be passed in to the parameters in the position order of the function definition, and the parameters can be passed in the way of keywords (formal parameter = formal parameter). In order to make the code easy to read and efficient, you can limit the transfer mode of parameters when calling the function through two special parameters, / and *:

def f(pos1, pos2, /, pos_or_kwd, *, kwd1, kwd2):
      -----------    ----------     ----------
        |                |                |
        |       Location parameter transfer or keyword parameter transfer        Keyword parameters
        |                                
         -- Position transfer parameter

It is easy to know from the figure that: / previous parameters can only be transferred in sequence through position order, / subsequent parameters can be transferred through position order or keyword, * subsequent parameters can only be transferred through keyword. Special parameters can be two at the same time, only one, or none (default). Examples are as follows:

>>> def f(pos_only, /, standard, *, kwd_only):
...     print(pos_only, standard, kwd_only)
...
# Correct transmission of parameters
>>> f(1, 2, kwd_only=3)
1 2 3
>>> f(1, standard=2, kwd_only=3)
1 2 3

# Error transmission parameter
>>> f(pos_only=1, 2, kwd_only=3)
  File "<input>", line 1
    f(pos_only=1, 2, kwd_only=3)
                               ^
SyntaxError: positional argument follows keyword argument
>>> f(1, 2, 3)
Traceback (most recent call last):
  File "<input>", line 1, in <module>
TypeError: f() takes 2 positional arguments but 3 were given

Unpack argument list

In short, if our arguments have been stored in the list, tuple or dictionary when calling the function, we can pass the values in the tuple and list into the function by * and the values in the dictionary can be passed into the function by * * as keyword parameters:

# Define function
>>> def add(x, y):
...     return x + y
... 

# Direct incoming error
>>> args = (3, 4)
... print(add(args))
Traceback (most recent call last):
  File "<input>", line 2, in <module>
TypeError: add() missing 1 required positional argument: 'y'

# Unpack tuple
>>> args = (3, 4)
... print(add(*args))
7

# Unpacking list
>>> args = [3, 4]
... print(add(*args))
7

# Unpack dict
>>> args = {"x": 1, "y": 2}
... print(add(**args))
3

# The number of args elements is inconsistent with the number of parameters required by add. An error is reported
>>> args = [3, 4, 7]
... print(add(*args))
Traceback (most recent call last):
  File "<input>", line 2, in <module>
TypeError: add() takes 2 positional arguments but 3 were given

Lambda expression

Usually we can use lambda expressions where anonymous functions are needed. It is just a syntax sugar. For example, to sort the elements of a list:

First call help(list.sort) to see the definition of the sort function:

>>> help(list.sort)
Help on method_descriptor:

# The self parameter is similar to this in other classes; key and reverse must use keywords to pass parameters
sort(self, /, *, key=None, reverse=False)
    # Default ascending order, return None
    Sort the list in ascending order and return None.
    # This sort method will modify the list and is a stable sort
    The sort is in-place (i.e. the list itself is modified) and stable (i.e. the
    order of two equal elements is maintained).
    # key requires a method to be passed in. When the sort method is executed, each element will be passed into the method in turn and sorted according to the return value
    If a key function is given, apply it once to each list item and sort them,
    ascending or descending, according to their function values.
    # Switch to descending sort
    The reverse flag can be set to sort in descending order.

After clarifying the definition, we now sort [(7,9), (5,6), (3,4), (6,5)] according to the first element, the second element and the sum of the two elements of each tuple:

Use non anonymous functions:

>>> def f(x):
...     return x[0]  # Sort by the first element of each tuple
... a = [(7, 9), (5, 6), (3, 4), (6, 5)]
... a.sort(key=f)
... print(a)
[(3, 4), (5, 6), (6, 5), (7, 9)]

>>> def f(x):
...     return x[0]
... a = [(7, 9), (5, 6), (3, 4), (6, 5)]
... a.sort(key=f, reverse=True)  #Sort by the first element of each tuple in descending order
... print(a)
[(7, 9), (6, 5), (5, 6), (3, 4)]

>>> def f(x):
...     return x[1]  # Sort by the second element of each tuple
... a = [(7, 9), (5, 6), (3, 4), (6, 5)]
... a.sort(key=f)
... print(a)
[(3, 4), (6, 5), (5, 6), (7, 9)]

>>> def f(x):
...     return x[0] + x[1]  # Sort by the sum of the two elements of each tuple
... a = [(7, 9), (5, 6), (3, 4), (6, 5)]
... a.sort(key=f)
... print(a)
[(3, 4), (5, 6), (6, 5), (7, 9)]

Using lambda expressions, there is no need to define functions in advance, and the writing method is very simple:

>>> a = [(7, 9), (5, 6), (3, 4), (6, 5)]
... a.sort(key= lambda x: x[0])
... print(a)
[(3, 4), (5, 6), (6, 5), (7, 9)]

>>> a = [(7, 9), (5, 6), (3, 4), (6, 5)]
... a.sort(key= lambda x: x[0], reverse=True)
... print(a)
[(7, 9), (6, 5), (5, 6), (3, 4)]

>>> a = [(7, 9), (5, 6), (3, 4), (6, 5)]
... a.sort(key= lambda x: x[1])
... print(a)
[(3, 4), (6, 5), (5, 6), (7, 9)]

>>> a = [(7, 9), (5, 6), (3, 4), (6, 5)]
... a.sort(key= lambda x: x[0] + x[1])
... print(a)
[(3, 4), (5, 6), (6, 5), (7, 9)]

Function Annotations

Since Python does not need to specify variable types, it will bring convenience to coding and some trouble to others calling functions, because it is not convenient for callers to find out the formal parameter types and return value types. Therefore, the function annotation can be used to add data type descriptions to formal parameters and function return values when defining functions. For example, we want to define a function to calculate the sum of two numbers:

# This function does not restrict the input parameter type. You can pass in either int type or str type
>>> def add(x, y):
...     return x + y
... print(add(1, 2))
... print(add("1", "2"))
3
12

# With function annotation, do you think you can limit the input parameters?
>>> def add(x: int, y: int) -> int:
...     return x + y
...
# It's of the no use. It only serves as advice and tips
>>> print(add("1", "2"))
12

# Use the help function to view
>>> help(add)
Help on function add in module __main__:

add(x: int, y: int) -> int

# Print function__ annotations__  Member variable view
>>> print(add.__annotations__)
{'x': <class 'int'>, 'y': <class 'int'>, 'return': <class 'int'>}

# If you want to assign a default value to the parameter while giving the parameter type description, the default value can be an expression, such as int = 1*10
>>> def add(x: int, y: int = 1) -> int:
...     return x + y
... 
>>> print(add(1))
2

# help can see the default value
>>> help(add)
Help on function add in module __main__:

add(x: int, y: int = 1) -> int

#  Print__ annotations__  Variables do not display default values
>>> print(add.__annotations__)
{'x': <class 'int'>, 'y': <class 'int'>, 'return': <class 'int'>}

Coding style

Finally, if you want to write easy to read and pleasing code, it is highly recommended to learn Episode: coding style.

Posted by ev5unleash on Wed, 01 Dec 2021 17:28:49 -0800