This article originated from personal public account: TechFlow, original is not easy, for attention


Recently, many friends contacted me from the background, saying that they want to learn Python, but they do not have a good introduction of materials. On the one hand, it is true that there are so many Python materials on the market that beginners may not know what to choose from. On the other hand, there are so many miscellaneous materials, ranging from 1+1 to deep learning, that there are not many good textbooks that focus purely on Python’s own syntax.

It just so happens that I recently came across a good introduction to Python in English, which I did some editing and translating for this article. This material is very pure, just basic Python syntax, for those who want to learn Python.

annotation

Python uses # to indicate a single line comment, and all lines following # are commented out.

# Single-line comments in Python are represented by #, after which all characters are considered commented.
Copy the code

Use three consecutive double quotation marks to indicate a multi-line comment. The content between two multi-line comment identifiers is treated as a comment.

""" Instead, a multi-line comment is represented by three double quotation marks, and everything in the double quotation marks will be treated as a comment.
Copy the code

Underlying variable types and operators

Numbers are defined the same way in Python as in other languages:

Get an integer
3
Get a floating point number
10.0
Copy the code

We use +, -, *, and/to represent the addition, subtraction, multiplication, and division operators respectively.

1 + 1   # = > 2
8 - 1   # = > 7
10 * 2  # = > 20
35 / 5  # = > 7.0
Copy the code

Note here that in Python2, the 10/3 operation yields 3 instead of 3.33333. Since both divisor and dividend are integers, Python automatically evaluates the integers and rounds the resulting quotient for us. If it’s 10.0/3, you get 3.33333. Python2 is no longer maintained, so you don’t have to worry about the details.

The problem is that Python is a weakly typed language, so if you get two variables in a function, you can’t tell their types directly. This leads to the possibility that the same calculator will yield different results, which can be very painful. So much so that programmers often need to manually add type converters to convert the dividend into floating point numbers when they do division operations.

Python3 corrected this by making sure that even if two integers are divisible, the result is always a floating point number.

If we wanted to get integers, we could do this:

5 // 3       # = > 1
- 5 // 3      # = > - 2
5.0 // 3.0   Floats too. # => 1.0 # works on floats too
5.0 // 3.0  # => -2.0
Copy the code

The two divisor signs indicate the exact division, and Python reserves the remainder for us.

In addition to the divisor operation, there is also a remainder operation, mathematically called modulo, which is represented by % in Python.

# Modulo operation
7 % 3  # = > 1
Copy the code

Power operations are supported in Python and can be done using the ** notation instead of calling extra functions:

# Exponentiation (x**y, x to the yth power)
2**3  # = > 8
Copy the code

When the operation is more complicated, we can use parentheses to force the order of the operation to change.

# Enforce precedence with parentheses
1 + 3 * 2  # = > 7
(1 + 3) * 2  # = > 8
Copy the code

Logical operations

Python uses uppercase True and False to represent True and False.

True  # => True
False  # => False
Copy the code

Use AND for and operations, or for or operations, and not for non-operations. Of instead of c + + or Java, &&, | | and! .

# negate with not
not True   # => False
not False  # => True

# Boolean Operators
# Note "and" and "or" are case-sensitive
True and False  # => False
False or True   # => True
Copy the code

In Python, True and False are actually 1 and 0, so no error is reported if we do the following, but it makes no logical sense.

# True and False are actually 1 and 0 but with different keywords
True + True # = > 2
True * 8    # = > 8
False - 5   # = > - 5
Copy the code

True==1; False == 0;

# Comparison operators look at the numerical value of True and False
0= =False  # => True
1= =True   # => True
2= =True   # => False
- 5! =False # => True
Copy the code

Be careful with the bool() function in Python. It does not convert to bool. If we execute this function, then only 0 will be treated as False and all other values will be True:

bool(0)     # => False
bool(4)     # => True
bool(- 6)    # => True
0 and 2     # = > 0
- 5 or 0     # = > - 5
Copy the code

Python uses == to determine equality, > means greater than, >= means greater than or equal to, < means less than, <= means less than or equal to,! Equals means unequal.

# Equality is ==
1= =1  # => True
2= =1  # => False

# Inequality is ! =
1! =1  # => False
2! =1  # => True

# More comparisons
1 < 10  # => True
1 > 10  # => False
2< =2  # => True
2> =2  # => True
Copy the code

We can assemble logical operations with and and or:

# Seeing whether a value is in a range
1 < 2 and 2 < 3  # => True
2 < 3 and 3 < 2  # => False
# Chaining makes this look nicer
1 < 2 < 3  # => True
2 < 3 < 2  # => False
Copy the code

Note the precedence between not, and, or, where not > and > OR. If it’s not clear, you can use parentheses to force a change in running order.

List and string

As for the judgment of list, we commonly use two kinds of judgment, one is just introduced ==, and the other is. We sometimes use is simply to judge, so what is the difference between the two? Let’s look at the following example:

a = [1.2.3.4]  # Point a at a new list, [1, 2, 3, 4]
b = a             # Point b at what a is pointing to
b is a            # => True, a and b refer to the same object
b == a            # => True, a's and b's objects are equal
b = [1.2.3.4]  # Point b at a new list, [1, 2, 3, 4]
b is a            # => False, a and b do not refer to the same object
b == a            # => True, a's and b's objects are equal
Copy the code

Python is an all-reference language, in which objects are represented by references. Is determines whether two references refer to the same object, while == determines whether two references refer to the same object. For example, if we compare a reference to an address, is is to determine whether two variables refer to the same address, such as XX Yanhe East Road. If == is the addressee of both addresses named Zhang SAN?

Obviously, people who live at the same address must both be named Joe, but two people who live at different addresses can both be named Joe, or they can have different names. So if a is B, then a == b must be true, and vice versa.

Strings are loosely restricted in Python. Both single and double quotation marks can be used to represent strings. I personally prefer single quotes because it’s easy to write.

Strings also support the + operation to concatenate two strings. In addition, we write two strings together, and Python concatenates them for us even if there is no + :

# Strings are created with " or '
"This is a string."
'This is also a string.'

# Strings can be added too! But try not to do this.
"Hello " + "world!"  # => "Hello world!"
# String literals (but not variables) can be concatenated without using '+'
"Hello " "world!"    # => "Hello world!"
Copy the code

We can use [] to find a character somewhere in the string and len to calculate the length of the string.

# A string can be treated like a list of characters
"This is a string"[0]  # => 'T'

# You can find the length of a string
len("This is a string")  # = > 16
Copy the code

We can prefix strings with f to indicate formatting operations, and we can support operations within formatting operations, such as nesting len functions. Note, however, that only Python3.6 and later support f operations.

# You can also format f-string literals (in Python 3.6+)
name = "Reiko"
f"She said her name is {name}." # => "She said her name is Reiko"
# You can basically put any Python statement inside the braces and it will be output in the string.
f"{name} is {len(name)} characters long." # => "Reiko is 5 characters long."
Copy the code

Finally, None. In Python, None is also an object, and all variables that are None refer to this object. As we said earlier, since all None points to the same address, we can use is to determine whether a variable is None. == is also possible, but we usually use is.

# None is an object
None  # => None

# Don't use the equality "==" symbol to compare objects to None
# Use "is" instead. This checks for equality of object identity.
"etc" is None  # => False
None is None   # => True
Copy the code

Now that we understand None, let’s go back to the bool() function we introduced earlier, which is really just a way of checking if a value is null. Default null values of all types are returned False, otherwise True. For example, 0, “”, [], {}, (), etc.

# None, 0, and empty strings/lists/dicts/tuples all evaluate to False.
# All other values are True
bool(None)# => False
bool(0)   # => False
bool("")  # => False
bool([])  # => False
bool({})  # => False
bool(())  # => False
Copy the code

All values passed in except those above will return True.

Variables and Sets

Input and output

Standard input and output in Python are input and print.

Print will print a string, and if it is not a string it will automatically call __str__ to print a string. By default, the output is wrapped. If you want to end a new line with a different character, you can pass in the end argument:

# Python has a print function
print("I'm Python. Nice to meet you!")  # => I'm Python. Nice to meet you!

# By default the print function also prints out a newline at the end.
# Use the optional argument end to change the end string.
print("Hello, World", end="!")  # => Hello, World!
Copy the code

When input is used, Python receives a string as input on the command line. We can pass a string in the input, which will be used as a prompt output:

# Simple way to get input data from console
input_string_var = input("Enter some data: ") # Returns the data as a string
# Note: In earlier versions of Python, input() method was named as raw_input()
Copy the code

variable

In Python, you don’t need to declare an object with a type, you just assign it. Python automatically associates the type, and if you use a variable that hasn’t been declared before, NameError will be raised.

# There are no declarations, only assignments.
# Convention is to use lower_case_with_underscores
some_var = 5
some_var  # = > 5

# Accessing a previously unassigned variable is an exception.
# See Control Flow to learn more about exception handling.
some_unknown_var  # Raises a NameError
Copy the code

Python supports ternary expressions, but the syntax is different from C++. Use the if else structure to write:

# if can be used as an expression
# Equivalent of C's '? :' ternary operator
"yahoo!" if 3 > 2 else 2  # => "yahoo!"
Copy the code

The previous code is equivalent to:

if 3 > 2:
    return 'yahoo'
else:
    return 2
Copy the code

list

Python uses [] to represent an empty list, which we can also initialize by filling directly with elements:

# Lists store sequences
li = []
# You can start with a prefilled list
other_li = [4.5.6]
Copy the code

Use append and pop to insert or delete elements at the end of a list:

# Add stuff to the end of a list with append
li.append(1)    # li is now [1]
li.append(2)    # li is now [1, 2]
li.append(4)    # li is now [1, 2, 4]
li.append(3)    # li is now [1, 2, 4, 3]
# Remove from the end with pop
li.pop()        # => 3 and li is now [1, 2, 4]
# Let's put it back
li.append(3)    # li is now [1, 2, 4, 3] again.
Copy the code

A list can access elements in a specified position by [] followed by a subscript or, if negative, in reverse order. -1 is the last element, -2 is the penultimate, and so on. If the number of elements accessed exceeds the array length, an IndexError is raised.

# Access a list like you would any array
li[0]   # = > 1
# Look at the last element
li[- 1]  # = > 3

# Looking out of bounds is an IndexError
li[4]  # Raises an IndexError
Copy the code

The list supports slicing, in which a specified section is copied from the list. We use the start: end format to get the slice. Note that this is a closed left open right interval. If the value is left blank, we can also add an additional parameter to indicate the step size. For example, [1:5:2] indicates that the element is retrieved from position 1 at step 2. The results obtained are [1, 3]. If the step size is set to -1, it represents reverse traversal.

# You can look at ranges with slice syntax.
# The start index is included, the end index is not
# (It's a closed/open range for you mathy types.)
li[1:3]   # Return list from index 1 to 3 => [2, 4]
li[2:]    # Return list starting from index 2 => [4, 3]
li[:3]    # Return list from beginning until index 3 => [1, 2, 4]
li[::2]   # Return list selecting every second entry => [1, 4]
li[::- 1]  # Return list in reverse order => [3, 4, 2, 1]
# Use any combination of these to make advanced slices
# li[start:end:step]
Copy the code

If we want to specify an interval in reverse order, start and end need to be reversed as well. For example, if I want to get the reverse order of the interval [3:6], I should write [6:3:-1].

If you use is to check the list before and after the copy, you will get False. You can use del to remove elements at a given location, or you can use the remove method.

# Make a one layer deep copy using slices
li2 = li[:]  # => li2 = [1, 2, 4, 3] but (li2 is li) will result in false.

# Remove arbitrary elements from a list with "del"
del li[2]  # li is now [1, 2, 3]

# Remove first occurrence of a value
li.remove(2)  # li is now [1, 3]
li.remove(2)  # Raises a ValueError as 2 is not in the list
Copy the code

The insert method specifies where to insert an element, and the index method queries the first occurrence of an element’s index.

# Insert an element at a specific index
li.insert(1.2)  # li is now [1, 2, 3] again

# Get the index of the first item found matching the argument
li.index(2)  # = > 1
li.index(4)  # Raises a ValueError as 4 is not in the list
Copy the code

Lists can be added. Two lists are added to indicate the combination of the elements in the list. Equivalent to using the extend method:

# You can add lists
# Note: values for li and for other_li are not modified.
li + other_li  # => [1, 2, 3, 4, 5, 6]

# Concatenate lists with "extend()"
li.extend(other_li)  # Now li is [1, 2, 3, 4, 5, 6]
Copy the code

To determine if an element is present in a list, we can use the in keyword to calculate the length of the list by using len:

# Check for existence in a list with "in"
1 in li  # => True

# Examine the length with "len()"
len(li)  # = > 6
Copy the code

tuple

A tuple is very close to a list, and a tuple is initialized by (). Unlike a list, a tuple is immutable. That is, once a tuple is created, it cannot be changed. If we modify the tuple, TypeError is raised.

# Tuples are like lists but are immutable.
tup = (1.2.3)
tup[0]      # = > 1
tup[0] = 3  # Raises a TypeError
Copy the code

Since the parentheses change the precedence, we define a tuple with a comma at the end, otherwise it will be treated as a single element:

# Note that a tuple of length one has to have a comma after the last element but
# tuples of other lengths, even zero, do not.
type((1))   # => <class 'int'>
type((1)),# => <class 'tuple'>
type(())    # => <class 'tuple'>
Copy the code

Tuple supports most of the operations in the list:

# You can do most of the list operations on tuples too
len(tup)         # = > 3
tup + (4.5.6)  # => (1, 2, 3, 4, 5, 6)
tup[:2]          # = > (1, 2)
2 in tup         # => True
Copy the code

We can unpack a tuple with multiple variables:

# You can unpack tuples (or lists) into variables
a, b, c = (1.2.3)  # a is now 1, b is now 2 and c is now 3
# You can also do extended unpacking
a, *b, c = (1.2.3.4)  # a is now 1, b is now [2, 3] and c is now 4
# Tuples are created by default if you leave out the parentheses
d, e, f = 4.5.6  # tuple 4, 5, 6 is unpacked into variables d, e and f
# respectively such that d = 4, e = 5 and f = 6
# Now look how easy it is to swap two values
e, d = d, e  # d is now 5 and e is now 4
Copy the code

Explain this line of code:

a, *b, c = (1.2.3.4)  # a is now 1, b is now [2, 3] and c is now 4
Copy the code

We put an asterisk in front of b to indicate that this is a list. So Python will assign the rest of the elements to B, with the other variables corresponding to the values.

The tuple itself is immutable, but the mutable elements in the tuple can be changed. Let’s say we have a tuple like this:

a = (3[4])
Copy the code

We can’t add or remove elements from a, but a contains a list of elements. We can change the list without raising the tuple:

a[1].append(0) # It's legal
Copy the code

dict

Dict is also a commonly used container in Python. It is the equivalent of a C++ map, a key-value pair that stores keys and values. We represent a dict with {} and separate key and value with:.

# Dictionaries store mappings from keys to values
empty_dict = {}
# Here is a prefilled dictionary
filled_dict = {"one": 1."two": 2."three": 3}
Copy the code

Dict keys must be immutable, so lists, sets, and dict cannot be the keys of another dict, or an exception will be thrown:

# Note keys for dictionaries have to be immutable types. This is to ensure that
# the key can be converted to a constant hash value for quick look-ups.
# Immutable types include ints, floats, strings, tuples.
invalid_dict = {[1.2.3] :"123"}  # => Raises a TypeError: unhashable type: 'list'
valid_dict = {(1.2.3) :1.2.3]}   # Values can be of any type, however.
Copy the code

We also use [] to find dict elements. We pass in a key to get a value, which is equivalent to get.

# Look up values with []
filled_dict["one"]  # = > 1
filled_dict.get('one') # = > 1
Copy the code

We can call the dict keys and values methods to get a list of all the keys and values in the dict. In Python3.7 or later, the order in which the results are returned may be different from the order in which they were inserted. In Python3.7 or later, Python guarantees that the order in which the results are returned is the same as the order in which they were inserted:

# Get all keys as an iterable with "keys()". We need to wrap the call in list()
# to turn it into a list. We'll talk about those later. Note - for Python
# versions <3.7, dictionary key ordering is not guaranteed
# not match the example below exactly. However, as of Python 3.7, dictionary
# items maintain the order at which they are inserted into the dictionary.
list(filled_dict.keys())  # => ["three", "two", "one"] in Python <3.7
list(filled_dict.keys())  # => ["one", "two", "three"] in Python 3.7+

# Get all values as an iterable with "values()". Once again we need to wrap it
# in list() to get it out of the iterable. Note - Same as above regarding key
# ordering.
list(filled_dict.values())  # => [3, 2, 1] in Python <3.7
list(filled_dict.values())  # => [1, 2, 3] in Python 3.7+
Copy the code

We can also use in to determine if a key is a dict.

# Check for existence of keys in a dictionary with "in"
"one" in filled_dict  # => True
1 in filled_dict      # => False
Copy the code

KeyError is raised if you use [] to look for a nonexistent key. If you use the get method, no exception is raised and None is returned:

# Looking up a non-existing key is a KeyError
filled_dict["four"]  # KeyError

# Use "get()" method to avoid the KeyError
filled_dict.get("one")      # = > 1
filled_dict.get("four")     # => None
# The get method supports a default argument when the value is missing
filled_dict.get("one".4)   # = > 1
filled_dict.get("four".4)  # = > 4
Copy the code

The setdefault method inserts a value for a key that does not exist, and does not overwrite it if it already exists:

# "setdefault()" inserts into a dictionary only if the given key isn't present
filled_dict.setdefault("five".5)  # filled_dict["five"] is set to 5
filled_dict.setdefault("five".6)  # filled_dict["five"] is still 5
Copy the code

We can use the update method to update the current dict with another dict, such as a.update(b). The key in the intersection of A and B will be overwritten by B, and the key that does not exist in A will be inserted:

# Adding to a dictionary
filled_dict.update({"four":4})  # => {"one": 1, "two": 2, "three": 3, "four": 4}
filled_dict["four"] = 4         # another way to add to dict
Copy the code

We can also use del to delete dict elements, again passing in only keys.

Python3.5 and older support unpacking a dict using ** :

{'a': 1, * * {'b': 2}}  # => {'a': 1, 'b': 2}
{'a': 1, * * {'a': 2}}  # => {'a': 2}
Copy the code

set

A set is a container for non-repeating elements. The elements in a set are all different and the same elements are deleted. We can initialize it by set(), or by {}. Note that when we use {}, we must pass in data or Python will confuse it with dict.

# Sets store ... well sets
empty_set = set()
# Initialize a set with a bunch of values. Yeah, it looks a bit like a dict. Sorry.
some_set = {1.1.2.2.3.4}  # some_set is now {1, 2, 3, 4}
Copy the code

The elements in a set must also be immutable, so lists cannot be passed into sets.

# Similar to keys of a dictionary, elements of a set have to be immutable.
invalid_set = {[1].1}  # => Raises a TypeError: unhashable type: 'list'
valid_set = {(1,), 1}
Copy the code

We can call the add method to insert elements into a set:

# Add one more item to the set
filled_set = some_set
filled_set.add(5)  # filled_set is now {1, 2, 3, 4, 5}
# Sets do not have duplicate elements
filled_set.add(5)  # it remains as before {1, 2, 3, 4, 5}
Copy the code

A set can also be thought of as a set, so it also supports some set-crossing and complement operations.

# Do set intersection with &
# compute intersection
other_set = {3.4.5.6}
filled_set & other_set  # => {3, 4, 5}

# Do set union with |
# evaluate union
filled_set | other_set  # => {1, 2, 3, 4, 5, 6}

# Do set difference with -
# Calculate the difference set
{1.2.3.4} - {2.3.5}  # = > {1, 4}

# Do set symmetric difference with ^
# This one is a little special, computes the symmetry set, that is, what is left after removing the duplicate elements
{1.2.3.4} ^ {2.3.5}  # => {1, 4, 5}
Copy the code

We can use greater-equal and less-than-equal signs to determine whether a set is a superset or a subset of another:

# Check if set on the left is a superset of set on the right
{1.2} > = {1.2.3} # => False

# Check if set on the left is a subset of set on the right
{1.2} < = {1.2.3} # => True
Copy the code

Like dict, we can use in to determine if an element is in a set. Copy is used to copy a set.

# Check for existence in a set with in
2 in filled_set   # => True
10 in filled_set  # => False

# Make a one layer deep copy
filled_set = some_set.copy()  # filled_set is {1, 2, 3, 4, 5}
filled_set is some_set        # => False
Copy the code

Control flow and iteration

statement

Judging statements in Python are very simple, and Python does not support switch, so we can only list if-else even with multiple conditions.

# Let's just make a variable
some_var = 5

# Here is an if statement. Indentation is significant in Python!
# Convention is to use four spaces, not tabs.
# This prints "some_var is smaller than 10"
if some_var > 10:
    print("some_var is totally bigger than 10.")
elif some_var < 10:    # This elif clause is optional.
    print("some_var is smaller than 10.")
else:                  # This is optional too.
    print("some_var is indeed 10.")
Copy the code

cycle

We can loop over the contents of a list using in, which is the basic looping method in Python.


""" For loops iterate over lists prints: dog is a mammal cat is a mammal mouse is a mammal """
for animal in ["dog"."cat"."mouse"] :# You can use format() to interpolate formatted strings
    print("{} is a mammal".format(animal))
Copy the code

If we want to loop over a range, we can use range. Range plus an argument for the sequence starting at 0, such as range(10) for all integers in the range [0, 10] :

""" "range(number)" returns an iterable of numbers from zero to the given number prints: 0 1 2 3 """
for i in range(4):
    print(i)
Copy the code

If we pass in two parameters, they represent the beginning and end of the iteration interval.

""" "range(lower, upper)" returns an iterable of numbers from the lower number to the upper number prints: 4 5 6 7 """
for i in range(4.8):
    print(i)
Copy the code

If we pass in a third element, it represents the step size that the variable increments with each loop.

""" "range(lower, upper, step)" returns an iterable of numbers from the lower number to the upper number, while incrementing by step. If step is not indicated, the default value is 1. prints: 4 6 """
for i in range(4.8.2):
    print(i)
Copy the code

If you use the enumerate function, you can iterate over both the subscript and elements of a list:

""" To loop over a list, and retrieve both the index and the value of each item in the list prints: 0 dog 1 cat 2 mouse """
animals = ["dog"."cat"."mouse"]
for i, value in enumerate(animals):
    print(i, value)
Copy the code

The while loop, like C++, executes when the condition is True and exits when it is false. And the judgment condition does not need parentheses:

""" While loops go until a condition is no longer met. prints: 0 1 2 3 """
x = 0
while x < 4:
    print(x)
    x += 1  # Shorthand for x = x + 1
Copy the code

Catch exceptions

Python uses try and except to catch exceptions, and we can restrict the type of exception after except. If more than one type can write more than one except, an else statement can be used to represent all the other types. The syntax ina finally statement must be executed whether or not an exception is raised:

# Handle exceptions with a try/except block
try:
    # Use "raise" to raise an error
    raise IndexError("This is an index error")
except IndexError as e:
    pass                 # Pass is just a no-op. Usually you would do recovery here.
except (TypeError, NameError):
    pass                 # Multiple exceptions can be handled together, if required.
else:                    # Optional clause to the try/except block. Must follow all except blocks
    print("All good!")   # Runs only if the code in try raises no exceptions
finally:                 # Execute under all circumstances
    print("We can clean up resources here")
Copy the code

With the operation

We use resources a lot in Python, and the most common is to open a file. When we open the file handle, we must close it, but if we code manually, we often forget to close it. And if the file is abnormal, an exception is raised. In this case, we can use the with statement instead of this part of the processing. Using with will automatically close the open resource at the end of the with block execution or when an exception is raised.

Here are several uses and functions of with:

# Instead of try/finally to cleanup resources you can use a with statement
Instead of using a try/finally statement to close the resource
with open("myfile.txt") as f:
    for line in f:
        print(line)

# Writing to a file
Write files using with
contents = {"aa": 12."bb": 21}
with open("myfile1.txt"."w+") as file:
    file.write(str(contents))        # writes a string to a file

with open("myfile2.txt"."w+") as file:
    file.write(json.dumps(contents)) # writes an object to a file

# Reading from a file
Use with to read files
with open('myfile1.txt'."r+") as file:
    contents = file.read()           # reads a string from a file
print(contents)
# print: {"aa": 12, "bb": 21}

with open('myfile2.txt'."r+") as file:
    contents = json.load(file)       # reads a json object from a file
print(contents)     
# print: {"aa": 12, "bb": 21}
Copy the code

iterable

Any object that can be iterated over using the in statement is called an iterable. It is not the same as an iterator. There is only an introduction to iterables. To learn more about iterators, go to the portal:

Python – Five minutes to learn about iterators and generators and hone your code skills

When we call dict keys, the result is an iterable.

# Python offers a fundamental abstraction called the Iterable.
# An iterable is an object that can be treated as a sequence.
# The object returned by the range function, is an iterable.

filled_dict = {"one": 1."two": 2."three": 3}
our_iterable = filled_dict.keys()
print(our_iterable)  # => dict_keys(['one', 'two', 'three']). This is an object that implements our Iterable interface.

# We can loop over it.
for i in our_iterable:
    print(i)  # Prints one, two, three
Copy the code

We can’t use subscripts to access an iterable, but we can use iter to convert it to an iterator, using the next keyword to get the next element. You can also convert it to a list, a list.

# However we cannot address elements by index.
our_iterable[1]  # Raises a TypeError

# An iterable is an object that knows how to create an iterator.
our_iterator = iter(our_iterable)

# Our iterator is an object that can remember the state as we traverse through it.
# We get the next object with "next()".
next(our_iterator)  # => "one"

# It maintains state as we iterate.
next(our_iterator)  # => "two"
next(our_iterator)  # => "three"

# After the iterator has returned all of its data, it raises a StopIteration exception
next(our_iterator)  # Raises StopIteration
 # We can also loop over it, in fact, "for" does this implicitly! our_iterator = iter(our_iterable) for i in our_iterator: print(i) # Prints one, two, three  # You can grab all the elements of an iterable or iterator by calling list() on it. list(our_iterable) # => Returns ["one", "two", "three"] list(our_iterator) # => Returns [] because state is saved Copy the code

function

Use the def keyword to define a function. If we specify the names of the parameters in the function, we can pass the parameters in the order defined by the function:

# Use "def" to create new functions
def add(x, y):
    print("x is {} and y is {}".format(x, y))
    return x + y  # Return values with a return statement

# Calling functions with parameters
add(5.6)  # => prints out "x is 5 and y is 6" and returns 11

# Another way to call functions is with keyword arguments
add(y=6, x=5)  # Keyword arguments can arrive in any order.
Copy the code

Arguments of any length can be preceded by *, which is converted to list:

# You can define functions that take a variable number of
# positional arguments
def varargs(*args):
    return args

varargs(1.2.3)  # => (1, 2, 3)
Copy the code

You can also specify keyword arguments of any length, preceded by ** to accept a dict:

# You can define functions that take a variable number of
# keyword arguments, as well
def keyword_args(**kwargs):
    return kwargs

# Let's call it to see what happens
keyword_args(big="foot", loch="ness")  # => {"big": "foot", "loch": "ness"}
Copy the code

Of course, we can use both, which will accept any argument:

# You can do both at once, if you like
def all_the_args(*args, **kwargs):
    print(args)
    print(kwargs)
""" all_the_args(1, 2, a=3, b=4) prints: (1, 2) {"a": 3, "b": 4} """
Copy the code

We can also use * and ** to unzip a list or dict when passing in parameters:

# When calling functions, you can do the opposite of args/kwargs!
# Use * to expand tuples and use ** to expand kwargs.
args = (1.2.3.4)
kwargs = {"a": 3."b": 4}
all_the_args(*args)            # equivalent to all_the_args(1, 2, 3, 4)
all_the_args(**kwargs)         # equivalent to all_the_args(a=3, b=4)
all_the_args(*args, **kwargs)  # equivalent to all_the_args(1, 2, 3, 4, a=3, b=4)
Copy the code

Arguments in Python can return multiple values:

# Returning multiple values (with tuple assignments)
def swap(x, y):
    return y, x  # Return multiple values as a tuple without the parenthesis.
                 # (Note: parenthesis have been excluded but can be included)

x = 1
y = 2
x, y = swap(x, y)     # => x = 2, y = 1
# (x, y) = swap(x,y) # Again parenthesis have been excluded but can be included.
Copy the code

The value of a global variable is not overwritten even if the name of a variable defined inside a function is the same as the global variable. To use a global variable inside a function, add the global keyword to indicate that it is a global variable:

# Function Scope
x = 5

def set_x(num):
    # Local var x not the same as global variable x
    x = num    # = > 43
    print(x)   # = > 43

def set_global_x(num):
    global x
    print(x)   # = > 5
    x = num    # global var x is now set to 6
    print(x)   # = > 6

set_x(43)
set_global_x(6)
Copy the code

Python supports functional programming, where we can return a function inside a function:

# Python has first class functions
def create_adder(x):
    def adder(y):
        return x + y
    return adder

add_10 = create_adder(10)
add_10(3)   # = > 13
Copy the code

Lambda can be used to represent anonymous functions in Python, using: as a separator, where: precedes the argument to the anonymous function and: follows the return value of the function:

# There are also anonymous functions
(lambda x: x > 2) (3)                  # => True
(lambda x, y: x ** 2 + y ** 2) (2.1)  # = > 5
Copy the code

We can also batch process and filter elements using the map and filter functions as parameters. For details on the use of Map, Reduce, and filter in Python, see the previous article:

Five minutes to learn about Map, Reduce and Filter

# There are built-in higher order functions
list(map(add_10, [1.2.3]))          # => [11, 12, 13]
list(map(max, [1.2.3], [4.2.1]))  # => [4, 2, 3]

list(filter(lambda x: x > 5[3.4.5.6.7]))  # = > [6, 7)
Copy the code

We can also initialize a list or dict with a combination of loops and judgments:

# We can use list comprehensions for nice maps and filters
# List comprehension stores the output as a list which can itself be a nested list
[add_10(i) for i in [1.2.3]]         # => [11, 12, 13]
[x for x in [3.4.5.6.7] if x > 5]  # = > [6, 7)

# You can construct set and dict comprehensions as well.
{x for x in 'abcddeef' if x not in 'abc'}  # => {'d', 'e', 'f'}
{x: x**2 for x in range(5)}  # => {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
Copy the code

The module

To import a Python module, use the import statement. To access functions or classes in a module.

# You can import modules
import math
print(math.sqrt(16))  # = > 4.0
Copy the code

We can also use the from import statement to import functions or classes in a module without having to write out the full path. Use from import * to import everything in a module (not recommended)

# You can get specific functions from a module
from math import ceil, floor
print(ceil(3.7))   # = > 4.0
print(floor(3.7))  # = > 3.0

# You can import all functions from a module.
# Warning: this is not recommended
from math import *
Copy the code

You can alias a method or class in a module using AS:

# You can shorten module names
import math as m
math.sqrt(16) == m.sqrt(16)  # => True
Copy the code

We can use dir to see the path of the module we are using:

# You can find out which functions and attributes
# are defined in a module.
import math
dir(math)
Copy the code

The reason for this is that if we also had a Python file called Math in our current path, it would override the system’s native Math module. This is especially important, as it can lead to a lot of weird bugs if you’re not careful.

class

Let’s look at a complete class, explained in the comments

# We use the "class" statement to create a class
class Human:

    # A class attribute. It is shared by all instances of this class
    # class attribute, which can be called directly from human.species, without instance
    species = "H. sapiens"

    # Basic initializer, this is called when this class is instantiated.
    # Note that the double leading and trailing underscores denote objects
    # or attributes that are used by Python but that live in user-controlled
    # namespaces. Methods(or objects or attributes) like: __init__, __str__,
    # __repr__ etc. are called special methods (or sometimes called dunder methods)
    # You should not invent such names on your own.
    The most basic constructor
    # Underlined functions and variables should not be used by users, where double-underlined functions and variables will not be overridden by subclasses
    Functions and attributes with double underscores are special attributes of the class
    def __init__(self, name):
        # Assign the argument to the instance's name attribute
        self.name = name

        # Initialize property
        self._age = 0

    # An instance method. All methods take "self" as the first argument
    All instances of a function in a class can be called. The first argument must be self
    # self indicates a reference to the instance
    def say(self, msg):
        print("{name}: {message}".format(name=self.name, message=msg))
 # Another instance method def sing(self): return 'yo... yo... microphone check... one two... one two... '  # A class method is shared among all instances # They are called with the calling class as the first argument  @classmethod # annotated to indicate that it is a class function # call through human.get_species, shared by all instances def get_species(cls): return cls.species  # A static method is called without a class or instance reference  @staticmethod Static functions can be called either by class name or by instance def grunt(a): return "*grunt*"  # A property is just like a getter. # It turns the method age() into an read-only attribute of the same name. # There's no need to write trivial getters and setters in Python, though.  @property # property annotation, similar to get, set methods # It's inefficient, so don't use it unless necessary def age(self): return self._age  # This allows the property to be set  @age.setter def age(self, age): self._age = age  # This allows the property to be deleted  @age.deleter def age(self): del self._age Copy the code

The detailed introduction of the above content has also been related to the article, you can view:

Python –slots, property and object naming conventions

Let’s look at using classes in Python:

# When a Python interpreter reads a source file it executes all its code.
# This __name__ check makes sure this code block is only executed when this
# module is the main program.
# This is the main function and the usual way to write the entry to the entire program
if __name__ == '__main__':
    # Instantiate a class
    Instantiate a class and get the object of the class
    i = Human(name="Ian")
    Execute the say method
    i.say("hi")                     # "Ian: hi"
    j = Human("Joel")
    j.say("hello")                  # "Joel: hello"
    # I and j are instances of Human and are called objects of the Human class
    # i and j are instances of type Human, or in other words: they are Human objects

    # Call our class method
    Class attributes are shared by all instances, once all changes take effect
    i.say(i.get_species())          # "Ian: H. sapiens"
    # Change the shared attribute
    Human.species = "H. neanderthalensis"
    i.say(i.get_species())          # => "Ian: H. neanderthalensis"
    j.say(j.get_species())          # => "Joel: H. neanderthalensis"

    Call static methods by class name
    # Call the static method
    print(Human.grunt())            # => "*grunt*"

    # Cannot call static method with instance of object 
    # because i.grunt() will automatically put "self" (the object i) as an argument
    Static methods cannot be called from an object, because the object passes in an instance of self, resulting in a mismatch
    print(i.grunt())                # => TypeError: grunt() takes 0 positional arguments but 1 was given

    # Update the property for this instance
    # Instance-level attributes are independent, and each object has its own property. Changes do not affect values in other objects
    i.age = 42
    # Get the property
    i.say(i.age)                    # => "Ian: 42"
    j.say(j.age)                    # => "Joel: 0"
    # Delete the property
    del i.age
    # i.age # => this would raise an AttributeError
Copy the code

Instance and object can be understood as the same concept. Instance is called instance and object is called object. Both refer to objects that are instantiated from the class.

inheritance

Inheritance allows a subclass to inherit variables and methods from its parent class, specify its own features, and override methods from its parent class. Generally we will put different classes in different files, import with import, can also implement inheritance.

from human import Human

# Specify the parent class(es) as parameters to the class definition
class Superhero(Human):

    # If the child class should inherit all of the parent's definitions without
    # any modifications, you can just use the "pass" keyword (and nothing else)
    # but in this case it is commented out to allow for a unique child class:
    # pass
    If we want to inherit all implementations of the parent class, we can use the keyword pass, which means skip. This does not change the implementation in the parent class

    # Child classes can override their parents' attributes
    species = 'Superhuman'

    # Children automatically inherit their parent class's constructor including
    # its arguments, but can also define additional arguments or definitions
    # and override its methods such as the class constructor.
    # This constructor inherits the "name" argument from the "Human" class and
    # adds the "superpower" and "movie" arguments:
    A subclass inherits its parent class's constructor completely, and we can modify it, such as adding additional parameters
    def __init__(self, name, movie=False, superpowers=["super strength"."bulletproofing"]):
 # add additional class attributes: # Additional new parameters self.fictional = True self.movie = movie # be aware of mutable default values, since defaults are shared self.superpowers = superpowers  # The "super" function lets you access the parent class's methods # that are overridden by the child, in this case, the __init__ method. # This calls the parent class constructor: A subclass can call the methods of its parent class using the super keyword super().__init__(name)  # override the sing method # override the sing method of the parent class def sing(self): return 'Dun, dun, DUN! '  # add an additional instance method Add method, subclass only def boast(self): for power in self.superpowers: print("I wield the power of {pow}!".format(pow=power)) Copy the code
if __name__ == '__main__':
    sup = Superhero(name="Tick")

    # Instance type checks
    # check inheritance
    if isinstance(sup, Human):
        print('I am human')
    # check type
    if type(sup) is Superhero:
        print('I am a superhero')

    # Get the Method Resolution search Order used by both getattr() and super()
    # This attribute is dynamic and can be updated
    Check the order of method queries
    # first itself, then up the inheritance order, finally object
    print(Superhero.__mro__)    # => (<class '__main__.Superhero'>,
                                # => <class 'human.Human'>, <class 'object'>)

    The same attribute subclass overrides the parent class
    # Calls parent method but uses its own class attribute
    print(sup.get_species())    # => Superhuman

    # Calls overridden method
    The same method overrides the parent class
    print(sup.sing())           # => Dun, dun, DUN!
 # Calls method from Human # inherits a method from a parent class sup.say('Spoon') # => Tick: Spoon  # Call method that exists only in Superhero # subclass-specific methods sup.boast() # => I wield the power of super strength! # => I wield the power of bulletproofing!  # Inherited class attribute sup.age = 31 print(sup.age) # = > 31  # Attribute that only exists within Superhero print('Am I Oscar eligible? ' + str(sup.movie)) Copy the code

Multiple inheritance

We create a bat class:


# Another class definition
# bat.py
class Bat:

    species = 'Baty'

    def __init__(self, can_fly=True):
        self.fly = can_fly

    # This class also has a say method
    def say(self, msg):
        msg = '... . . '
        return msg

    # And its own method as well
    # Unique sonar method for Bats
    def sonar(self):
        return ')))... ((('
 if __name__ == '__main__': b = Bat() print(b.say('hello')) print(b.fly) Copy the code

Superhero and Bat we’ll create a Superhero class.

# And yet another class definition that inherits from Superhero and Bat
# superhero.py
from superhero import Superhero
from bat import Bat

# Define Batman as a child that inherits from both Superhero and Bat
class Batman(Superhero, Bat):

    def __init__(self, *args, **kwargs):
        # Typically to inherit attributes you have to call super:
        # super(Batman, self).__init__(*args, **kwargs)      
        # However we are dealing with multiple inheritance here, and super()
        # only works with the next base class in the MRO list.
        # So instead we explicitly call __init__ for all ancestors.
        # The use of *args and **kwargs allows for a clean way to pass arguments,
        # with each parent "peeling a layer of the onion".
        Call the constructor of each parent class by class name
        Superhero.__init__(self, 'anonymous', movie=True, 
                           superpowers=['Wealthy'], *args, **kwargs)
        Bat.__init__(self, *args, can_fly=False, **kwargs)
        # override the value for the name attribute
        self.name = 'Sad Affleck'

    # override the sing method of the parent class
    def sing(self):
        return 'nan nan nan nan nan batman! '
Copy the code

Execute this class:

if __name__ == '__main__':
    sup = Batman()

    # Get the Method Resolution search Order used by both getattr() and super().
    # This attribute is dynamic and can be updated
    # can see the method of the query sequence is superhero along the line to the human first, and then the bat
    print(Batman.__mro__)       # => (<class '__main__.Batman'>, 
                                # => <class 'superhero.Superhero'>, 
                                # => <class 'human.Human'>, 
                                # => <class 'bat.Bat'>, <class 'object'>)

    # Calls parent method but uses its own class attribute
    # only superhero has get_species
    print(sup.get_species())    # => Superhuman

    # Calls overridden method
    print(sup.sing())           # => nan nan nan nan nan batman!

    # Calls method from Human, because inheritance order matters
    sup.say('I agree')          # => Sad Affleck: I agree
 # Call method that exists only in 2nd ancestor Call the bat sonar method print(sup.sonar()) # = >)))... (((  # Inherited class attribute sup.age = 100 print(sup.age) # = > 100  # Inherited attribute from 2nd ancestor whose default value was overridden. print('Can I fly? ' + str(sup.fly)) # => Can I fly? False Copy the code

The advanced

The generator

We can create a generator with the yield keyword that stops at the yield keyword each time we invoke it. The next time it is called, the execution starts from yield and continues:

# Generators help you make lazy code.
def double_numbers(iterable):
    for i in iterable:
        yield i + i

# Generators are memory-efficient because they only load the data needed to
# process the next value in the iterable. This allows them to perform
# operations on otherwise prohibitively large value ranges.
# NOTE: `range` replaces `xrange` in Python 3.
for i in double_numbers(range(1.900000000)) :# `range` is a generator.
    print(i)
    if i >= 30:
        break
Copy the code

In addition to yield, we can use the () parentheses to generate a generator:

# Just as you can create a list comprehension, you can create generator
# comprehensions as well.
values = (-x for x in [1.2.3.4.5])
for x in values:
    print(x)  # prints -1 -2 -3 -4 -5 to console/terminal

# You can also cast a generator comprehension directly to a list.
values = (-x for x in [1.2.3.4.5])
gen_to_list = list(values)
print(gen_to_list)  # => [-1, -2, -3, -4, -5]
Copy the code

For more on generators and iterators, check out the following article:

Five minutes will take you through iterators and generators and strengthen your code

A decorator

After we introduce wraps in Functools, we can create a decorator. Decorators can wrap a layer of additional logic around a function without modifying its internal code:

# Decorators
# In this example `beg` wraps `say`. If say_please is True then it
# will change the returned message.
from functools import wraps

def beg(target_function):
    @wraps(target_function)
    # If please is True, print an additional please! I am poor :(
    def wrapper(*args, **kwargs):
        msg, say_please = target_function(*args, **kwargs)
        if say_please:
            return "{} {}".format(msg, "Please! I am poor :(")
        return msg

    return wrapper

@beg
def say(say_please=False):
    msg = "Can you buy me a beer?"
    return msg, say_please

print(say())                 # Can you buy me a beer?
print(say(say_please=True))  # Can you buy me a beer? Please! I am poor :(
Copy the code

The decorator has previously been detailed in a special article, which can be moved to the following portal:

Finish the Python decorator and stop panicking after the interview

At the end

I don’t know how many of you can see the end, but the author is really good at covering almost all of Python’s basic operations. If you can read and understand it, then Python is a beginner’s language.

The original author wrote a Python file, and everything is in Python comments. I made patches and additional descriptions on top of it. If you want to get the original, you can check it out, or you can get it by replying to LearnPython.

If you already know the basics of another language, I don’t think you should have to read this article in 30 minutes. Of course, learning a language in 30 minutes is impossible and not what I advocate. But at least through this article we can be familiar with Python syntax, know the general operation, the rest of us to write code to experience and use.

In my experience, in the early stages of learning a new language, constant research is inevitable. Hopefully, this article will serve as a reference when you’re working with Python.

Today’s article here, the original is not easy, need your attention, your lift a finger for me is very important.