【建议收藏】五年程序员写给小白看的Python基础知识

32000字的长文,建议先收藏后阅读,如果能够点赞转发那就太感谢啦~

话不多说,我们正式开始。

安装 Python

在开始学习 python 之前,我们先要安装 python。安装 python 的步骤根据不同的操作系统会有些差异,以下是几种常见的操作系统下的安装方法

Ubuntu

命令行下运行

apt-get install python3

Mac

命令行下运行

brew install python

Windows

在 python 官网 https://www.python.org/downloads/windows/ 上,选择最新的 Python 安装包,下载安装即可。

安装完 Python,我们在命令行输入 python3,就可以启动 python 解释器,像下面这样

$ python3
Python 3.9.6 (v3.9.6:db3ff76da1, Jun 28 2021, 11:49:53)
[Clang 6.0 (clang-600.0.57)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>>

接下来我们就可以开始我们的Python编程之旅了。

初识Python

酷酷的 Python

在开始学习编程之前,我们先来看一个有趣的例子,我们在我们的 Python 解释器中,贴入下面这一行代码

print('\n'.join([''.join([('Love'[(x-y) % len('Love')] if ((x*0.04)**2+(y*0.1)**2-1)**3-(x*0.04)**2*(y*0.1)**3 <= 0 else ' ') for x in range(-30, 30)]) for y in range(30, -30, -1)]))

然后点击运行,看看会有什么结果?

结果是长这样的

                                                            
            veLoveLoveL               LoveLoveLov           
        eLoveLoveLoveLoveLov     LoveLoveLoveLoveLove       
     oveLoveLoveLoveLoveLoveLoveLoveLoveLoveLoveLoveLove    
    oveLoveLoveLoveLoveLoveLoveLoveLoveLoveLoveLoveLoveLo   
   oveLoveLoveLoveLoveLoveLoveLoveLoveLoveLoveLoveLoveLove  
  oveLoveLoveLoveLoveLoveLoveLoveLoveLoveLoveLoveLoveLoveLo 
  veLoveLoveLoveLoveLoveLoveLoveLoveLoveLoveLoveLoveLoveLov 
  eLoveLoveLoveLoveLoveLoveLoveLoveLoveLoveLoveLoveLoveLove 
  LoveLoveLoveLoveLoveLoveLoveLoveLoveLoveLoveLoveLoveLoveL 
   veLoveLoveLoveLoveLoveLoveLoveLoveLoveLoveLoveLoveLoveL  
   eLoveLoveLoveLoveLoveLoveLoveLoveLoveLoveLoveLoveLoveLo  
    oveLoveLoveLoveLoveLoveLoveLoveLoveLoveLoveLoveLoveLo   
     eLoveLoveLoveLoveLoveLoveLoveLoveLoveLoveLoveLoveLo    
       veLoveLoveLoveLoveLoveLoveLoveLoveLoveLoveLoveL      
        LoveLoveLoveLoveLoveLoveLoveLoveLoveLoveLoveL       
          eLoveLoveLoveLoveLoveLoveLoveLoveLoveLove         
            veLoveLoveLoveLoveLoveLoveLoveLoveLov           
               veLoveLoveLoveLoveLoveLoveLoveL              
                  veLoveLoveLoveLoveLoveLov                 
                     veLoveLoveLoveLoveL                    
                         eLoveLoveLo                        
                            eLove                           
                              v                             
                                                    

有没有惊讶到?对,Python 就是这么酷,一行代码就可以画个爱心❤️。这个例子的代码看不懂没关系,在学习了相关的基础知识后,我们会详细的讲解这个例子。

打印字符串

我们从一段最简单的代码来开始学习 Python

print("Hello world")

这段代码会打印出 "Hello world" 这样一句话。代码里的 print 是一个函数,"Hello world" 是一个字符串。关于函数和字符串,我们会在后面的内容里详细讲解。

注释

在Python中,注释用井号(# )标识,像下面这样

# 这是一段注释

注释不会被 Python 解释器执行,井号后面的内容都会被Python解释器忽略。注释一般用来对代码做注解,主要是为了让程序更易于理解。

数和表达式

表达式是运算符和操作数构成的序列,我们看几个例子就很清楚

1 + 1 # 加法运算,结果是 2
3 / 2 # 除法运算,结果是 1.5
3 // 2 # 整除运算,结果是 1
3 % 2 # 求余数,结果是 1
2 ** 3 # 指数运算,结果是 8

变量

变量很好理解,就是给一个值起一个名字,比如 a = 3,a 就是变量名,3就是它的值。b = "hello",b 是变量名,"hello" 是它的值。这个将变量设成某一个值的过程叫做赋值。一旦变量被赋值,我们就可以在表达式中使用它,像下面这样

a = 3 # 将变量 a 设成 3
a * 5 # 将变量 a 乘以 5
b = "hello" # 将变量 b 设成字符串 hello
print(b) # 打印变量 b 的值

语句

语句可以理解成做一件事。我们前面提到的 a = 3 是一个赋值语句,print("hello") 是一个函数调用语句。Python 中还有很多其它的语句,我们在后面的内容里会详细的讲解。

函数

函数就是一个实现特定功能的程序,比如我们前面提到的 print 是一个函数,它实现的是打印的功能。python 中还有许多其它的函数,比如

pow(2, 3) # 计算2的3次方,结果是 8
abs(-10) # 计算-10的绝对值,结果是 10
round(1.8) # 计算1.8四舍五入后的值,结果是 2

函数怎么使用,怎么定义函数,我们在后面的内容会展开详细讲解。

模块

模块是一组功能的组合,模块中可以有函数、变量等等。在 python 中我们会经常用到模块。比如我们要用到一些数学函数,这时可以使用 math 这个模块。

首先我们用关键字 import 来指定要使用它,像下面这样

import math

接下来我们使用 math 模块中的函数,用下面的方式

math.floor(2.1) # 使用 math 模块中的 floor 函数对2.1作向下取整,结果是 2
math.ceil(2.1) # 使用 math 模块中的 ceil 函数对2.1作向上取整,结果是 3
math.sqrt(2) # 使用 math 模块中的 sqrt 函数对2求平方根,结果是 1.4142135623730951

使用 math 模块中定义的变量,可以用下面的方式

math.pi # 输出 3.141592653589793

模块就像是一个工具箱,使用模块就好像打开了一个工具箱,我们选择我们需要的工具,来做我们想做的事。

好,以上就是这一节的全部内容。这一节我们主要是对 Python 的一些基本概念做了个粗浅的介绍,让大家对 Python 有个初步的认识。在接下来的内容里,我们将逐步深入地学习。下一节,我们来看一下 Python 中的几种基本数据类型。

Python 基本数据类型

Python中的数据类型主要有这样几种

  • 数字
  • 字符串
  • 列表
  • 元组
  • 字典

下面我们来逐个讲解。

数字

Python里有两种数字类型:整数和浮点数。数字和数字之间可以做各种数值运算,如下

# 整数
2 + 3 # 加法运算,结果 5
2 - 3 # 减法运算,结果 -1 
3 // 2 # 整除运算,结果 1 
3 / 2 # 浮点数除法,结果 1.5
2 ** 3 # 指数运算,结果 8

# 浮点数
2.1 + 3.1 # 加法运算,结果 5.2
2.1 - 3.1 # 减法运算,结果 -1.0
3.1 / 2.1 # 浮点数除法运算,结果 1.4761904761904763
3.1 * 2.1 # 乘法运算,结果 6.51
3.1 ** 0.5 # 指数运算,结果 1.760681686165901

字符串

字符串顾名思义,就是一串字符,下面是几个定义字符串的例子

a = 'hello' 

字符串可以单引号引起来,也可以用双引号引起来,并没有区别,比如上面的字符串也可以写成

a = "hello"

双引号引起来的字符串中可以包含单引号,如下

a = "I'm from China" # 如果双引号引起来的字符串中可以包含单引号

同样,单引号引起来的字符串中可以包含双引号

a = 'I told him, "Python is the best programming language"'

但如果用单引号引起来的字符串中包含单引号,或者双引号引起来的字符串中包含双引号,就需要用反斜杠(\)进行转义,如下

a = 'I\'m from China'
a = "he says \"hello\""

既然字符串是一串字符的组合,我们就可以截取字符串,截取字符串使用方括号[],如下

a = "hello"
print(a[0]) # 打印第一个字符,输出 h
print(a[1]) # 打印第二个字符,输出 e
print(a[-1]) # -1 表示最后一个字符,输出 o

字符串支持几种常见的操作

修改大小写

name = "albert einstein"
name.title() # 每个字母首字母大写,输出 'Albert Einstein'
name.upper() # 所有字母大写,输出 'ALBERT EINSTEIN'
name.lower() # 所有字母小写,输出 'albert einstein'

拼接字符串

first_name = "albert"
last_name = "einstein"
first_name + " " + last_name # 输出 'albert einstein'

删除空白

a = "  hello "
a.strip() # strip 方法会删除字符串开始处和结尾处的空格,所以输出 'hello'

使用 join 方法合并多个字符串

print(",".join(["name", "age", "location"])) 

上面的代码中 join 方法将括号內的字符串合并,不同字符串之间用逗号(,)分隔,所以上面的代码会输出 name,age,location

使用 split 方法将字符串拆分为序列

"name,age,location".split(",")

split 方法将字符串拆分,括号內指定按什么符号分隔,这里是按逗号(,),所以上面的代码输出 ['name', 'age', 'location']

Python 中有一些特殊的字符串会有特殊的含义,其中一个就是换行符。换行符用 \n 表示,如下

newline = '\n' # 这里是一个换行符

下面我们 print 一个带有换行符的字符串

print("Huawei\nXiaomi")

因为带了换行符,这段代码的结果是这样的

Huawei
Xiaomi

说到字符串,就不得不提到格式化字符串。什么是格式化字符串呢?格式化字符串就是对数据进行格式化输出,听着很抽象,我们来看一个例子就很清楚了

print("My name is %s" % ("John")) 

这里,"My name is %s" 相当于一个模板,%s 的意思是说我这个位置先占个位,具体填什么值稍后再说。那么到底填什么值呢?这个值就是后面括号里的 "John",所以上面的代码会输出 'My name is John'。这就是格式化输出。

这里的 %s 称为转换说明符,它的作用除了占个位,其实还有更一层的意思,就是表示我这个位置上的值必须是一个字符串。说到这儿,大家一定想到了,既然有字符串的转换说明符,那一定也有整数,浮点数的转换说明符。是的,我们看下面的代码

print("I am %d year-old" % (27)) # %d 表示整数类型,输出 'I am 27 year-old'
print("deposit rate is %f" % (5.35)) # %f 表示浮点数类型,输出 'deposit rate is 5.350000'

除了用百分号(%),我们还可以用format方法来做格式化字符串。原理是类似的,只是写法不同,比如

print("{} is {} year-old".format("Jane", 5))

这里我们用 {} 表示这里需要填入一个值。使用 {} 有一个好处,就是我们不需要指定这个值的类型,这也是它的方便之处。

在 {} 里我们可以指定一个数字,比如 {1} 这样,这个大括号里数字代表的这里应该填入的是后面 format 方法里的第几个参数( {0} 对应第一个参数,{1} 对应第二个参数,等等),比如

print("{0}, {1} and {2}".format("first", "second", "third")) # 输出 first, second and third
print("{2}, {1} and {0}".format("first", "second", "third")) # 输出 third, second and first

如果是数字类型的,还可以指定精度,比如

print("{:.2f}".format(3.1415926)) # 显示小数点后2位,输出 3.14

以上就是关于字符串。

列表

列表是是一个可以包含多个元素的数据结构,列表中的每个元素可以是数字、字符串、也可以是列表,看几个例子

squares = [1, 4, 9, 16, 25] # 全是数字组成的列表
names = ['jack', 'jane', 'jammy'] # 全是字符串组成的列表
iphone = ['iphone 11', 5000] # 由字符串和数字组成的列表
database = [['iphone 11', 5000], ['huawei p30', 3000]] # 二维列表,每个元素是列表

下面,我们来看一下列表的常用基本操作。

访问列表元素

# 注意:下标从0开始,而不是从1开始
squares = [1, 4, 9, 16, 25]
print(squares[0]) # 输出 1
print(database[1]) # 输出 ['huawei p30', 3000]

# 如果索引超出范围,会报错
print(squares[6]) # squares 列表一共只有5个元素,这里的6代表要访问第7个元素,所以会报错

# 可以指定负索引
print(squares[-1]) # 表示访问 squares 列表的最后一个元素,输出 25

获取列表长度,用 len 函数

print(len(squares)) # 输出 5

修改列表中的元素的值

squares[4] = 30 # 将下标为4的元素设成30
print(squares) # 输出 [1, 4, 9, 16, 30]

words = ['Python', 'is', 'a', 'greet', 'language']
words[3] = 'great' # 将 words 中下标为3的元素改成 great
print(words) # 输出 ['Python', 'is', 'a', 'great', 'language']

往列表中添加元素

squares = [1, 4, 9, 16, 25]
squares.append(36) # 将元素36添加到 squares 末尾
print(squares) # 输出 [1, 4, 9, 16, 25, 36]

在指定位置插入元素

names = ['jack', 'jane', 'jammy']
names.insert(0, 'henry') # 在 names 中下标为0的位置插入'henry'
print(names) # 输出 ['henry', 'jack', 'jane', 'jammy']
names.insert(3, 'mary') # 在 names 中下标为3的位置插入'mary'
print(names) # 输出 ['henry', 'jack', 'jane', 'mary', 'jammy']

从列表中删除元素

names = ['jack', 'jane', 'jammy']
del names[0] # 删除下标为0的元素
print(names) # 输出 ['jane', 'jammy']

names = ['jack', 'jane', 'jammy']
del names[2] # 删除下标为2的元素
print(names) # 输出 ['jack', 'jane']

根据值删除元素

names = ['jack', 'jane', 'jammy']
names.remove('jane') # 从 names 中删除 'jane' 这个元素 
print(names) # 输出 ['jack', 'jammy']

列表的切片操作

squares = [1, 4, 9, 16, 25]
print(squares[1:3]) # 打印 squares 中从下标1到3(不包括3)的所有元素,输出 [4, 9]

# 支持指定步长
print(squares[::2]) # squares 中每隔2个元素取一个,也就是取出 squares 中下标为0,2,4的元素,输出 [1, 9, 25]

拼接列表

[1, 2, 3] + [4, 5, 6] # 输出 [1, 2, 3, 4, 5, 6]

乘法

# 乘法
[1] * 5 # 输出 [1, 1, 1, 1, 1]

判断列表中是否包含值

names = ['jack', 'jane', 'jammy']
'jack' in names # names 中是否存在 'jack' 这个值,输出 True
'henry' in names # names 中是否存在 'henry' 这个值,输出 False

计算最大值和最小值

squares = [1, 4, 9, 16, 25]
min(squares) # 输出 squares 中最小的元素 1
max(squares) # 输出 squares 中最大的元素 25

排序

numbers = [1, 5, 2, 8, 3]
numbers.sort() # 将 numbers 中元素从小到大排序
print(numbers) # 输出 [1, 2, 3, 5, 8]

# sorted函数也可以对列表排序,和上面sort不同的是
# sort修改列表中的元素,而sorted保持列表中的元素不变,但是把结果返回出来
numbers = [1, 5, 2, 8, 3]
sorted(numbers) 
print(numbers) # 输出 [1, 5, 2, 8, 3]
print(sorted(numbers)) # 输出 [1, 2, 3, 5, 8]

# 降序排序
result = sorted(numbers, reverse=True) # 可以指定参数  reverse=True 来进行降序排序
print(result) # 输出 [8, 5, 3, 2, 1]

查找值第一次出现的下标

names = ['jack', 'jane', 'jammy']
names.index('jane')  # 结果是 1,因为 'jane' 在列表中对应下标1的位置

扩展列表

a = [1, 2, 3]
b = [4, 5, 6]
a.extend(b) # 将列表 b 的元素填入到列表 a 中
print(a) # 输出 [1, 2, 3, 4, 5, 6]

遍历列表中的元素

names = ['jack', 'jane', 'jammy']
for name in names: # 遍历 names 中的每一个元素,把它打印出来
    print(name)

列表推导式

squares = [x**2 for x in [1, 2, 3, 4, 5]] # 对列表中的每个元素计算平方
print(squares) # 输出 [1, 4, 9, 16, 25]

以上就是关于列表。

元组

元组与列表很相似,唯一的区别就是列表可修改,元组不可修改。元组的定义使用圆括号,如下

squares = (1, 4, 9, 16, 25)

上面 squares 就是一个元组。

要访问元组中的值,我们可以使用和列表相同的方法,比如

print(squares[0]) # 打印 squares 中下标为0的元素,输出 1
print(squares[1:3]) # 打印 squares 中下标从1到3(不包括3)的元素, 输出 4,9

前面说到元组的值是不可修改的,我们来尝试修改一下它,看看会发生什么

squares[2] = 10 # 修改下标为2的元素,会得到下面的错
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Input In [5], in <cell line: 2>()
      1 # 元组中的值不可修改
----> 2 squares[2] = 10

TypeError: 'tuple' object does not support item assignment

这里程序报错,告诉我们元组是不可被修改的。

字典

字典是一种映射类型,是键到值的映射。为了帮助理解,我们可以把 Python 中的字典和我们日常生活中的字典做类比。假设有一本英汉字典,我们想要查找某一个英文单词对应的中文含义,我们会怎么做呢?我们会首先在字典里找到这个英文单词的条目,然后查看它的中文含义。同样的,Python 中的字典也是这样存储信息的。字典的键值对就好比英汉字典中的英文单词和中文含义,给我们一个键,我们就能查到它对应的值。

下面是一个电话号码簿的例子

tel = {"john": "111", "jane": "222", "jack": "333"}

获取键对应的值

tel["john"] # 获取 john 的电话号码,结果 '111'

修改键对应的值

tel['john'] = '555'

删除一个键

del tel['john'] # 把 john 的号码从号码簿中删除
print(tel) # 输出 {'jane': '222', 'jack': '333'}

检查字典中是否包含键

'jane' in tel # 结果 True

访问不存在的键会报错

tel = {"john": "111", "jane": "222", "jack": "333"}
tel['henry'] # 会报下面的错
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
Input In [28], in <cell line: 2>()
      1 tel = {"john": "111", "jane": "222", "jack": "333"}
----> 2 print(tel["henry"])

KeyError: 'henry'

get 方法获取值

print(tel.get("henry")) # 不会报错,输出 None
print(tel.get("henry", "N/A")) # 这里传入了一个参数告诉 get 方法,如果 henry 这个键不存在,就输出 'N/A'

keys 方法获取字典中所有的键

print(tel.keys()) # 输出 dict_keys(['john', 'jane', 'jack'])

values 方法获取字典中所有的值

print(tel.values()) # 输出 dict_values(['111', '222', '333'])

items 方法返回包含字典中所有键值对的列表

print(tel.items()) 输出 dict_items([('john', '111'), ('jane', '222'), ('jack', '333')])

setdefault 方法获取键对应的值,当键不存在的时候,setdefault 给这个键设定一个默认值

tel = {"john": "111", "jane": "222", "jack": "333"}
tel.setdefault('henry', 'N/A') # 因为 henry 这个键不存在,把它的值设成 'N/A'
print(tel) # 输出 {'john': '111', 'jane': '222', 'jack': '333', 'henry': 'N/A'}

以上就是这一节的全部内容。这一节我们详细的介绍了 Python 中的几种基本的数据类型,在下一节中我们将介绍计算机程序中的另一个要素——语句。

语句

Python 中的语句主要有以下几类

  • import 语句
  • 赋值语句
  • 条件语句
  • 循环语句

下面我们来逐个看下每种类型的语句。

import 语句

前面说到过,import 语句用于导入模块。模块就好比是一个工具箱,导入模块就是说,我们把这个工具箱准备好,接下来我们要打开工具箱使用里面的工具了。有这样几种导入方式

导入时重命名模块

import math as m # 将 math 模块重命名成 m
m.sqrt(2) 

导入模块中的指定函数

from math import sqrt # 导入 math 模块中的 sqrt 函数
sqrt(2) # 调用 sqrt 函数

导入模块中的一切

from math import * # 星号*代表导入一切内容,包括函数、变量等等,下面的 sqrt,floor 都是 math 模块中的函数
sqrt(2) 
floor(2.1) 

赋值

Python 中有这样几种不同的赋值方式

单个变量赋值,这是最简单的赋值方式

x = 1

同时给多个变量赋值

x, y = (1, 2)
print(x) # 输出 1
print(y) # 输出 2

链式赋值

x = y = z = 1
print(x, y, z) # 输出 1 1 1

增强赋值

x += 1 # 相当于 x = x + 1

缩进

Python 中使用缩进来创建代码块,像下面这样

a = 5
for i in range(10):
    if i == a:
        print(i)
        break

在上面的代码中,if 这一行比上面的 for 这一行缩进了4个空格,从 if 开始的这三行是属于 for 语句的代码块。if 下面的 print 这一行比 if 这一行又缩进了4个空格。,从 print 开始的这两行是属于 if 语句的代码块。

Python 中对于缩进量没有限制,可以是3个空格,可以是4个空格,也可以是一个tab,但是所有的缩进量必须统一。也就是,如果用3个空格作为缩进量,那代码中所有的缩进量都必须是3个空格。一般推荐的做法是:使用4个空格作为缩进量

条件语句

条件语句用来测试条件是真是假,然后根据测试的结果执行相应的代码块,条件语句包括 if 语句,elif 子句和 else 子句。我们用代码来举例

a = 0
if a > 0:
    print("a is positive")
elif a == 0:
    print("a is zero")
else:
    print("a is negative")

if 判断条件是否为真,当 if 判断不为真时,会判断 elif 子句(可以存在多个 elif 子句),如果 elif 都不为真,那么执行 else。

上面的例子中,因为 a = 0,所以 if a > 0 为假,而 elif a == 0 为真,所以就执行 elif 下面的代码块,于是输出 a is zero。

当我们要检查多个条件时,可以用 and 和 or 关键字。

使用 and 表示只有当 and 左右两边的条件都满足,这个结果才为真,否则就为假,如下

age1 = 20
age2 = 16
age1 < 18 and age2 < 18 # 结果为False,因为 age1 < 18 为假

使用 or 表示只要 or 左右两边的条件中有一个满足,这个结果就为真,如果两边条件都不满足,那就为假,比如

age1 = 20
age2 = 16
age1 < 18 or age2 < 18 # 结果为True,因为 age2 < 18为真

循环语句

循环是在条件判断为真时,不断的执行代码块,直到条件判断为假,结束循环。循环有 while 循环和 for 循环。

while 循环如下

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

x 每次加1,只要 x <= 10,就不断地执行代码块,直到 x 的值大于10为止。上面的代码会输出下面的结果

1
2
3
4
5
6
7
8
9
10

for 循环如下

text = ["John", "is", "an", "analyst"]
for word in text:
    print(word)

text 是一个列表,里面包含4个单词,for 循环中我们会遍历 text 中所有的元素,将它赋给 word 变量,然后在循环体內把 word 打印出来。上面的代码会输出下面的结果

John
is
an
analyst

和 for 循环经常一起出现的,有一个 range 函数,非常好用。range 函数的作用是返回一个整数序列,比如

range(10) # 创建一个从0-9的10个整数的序列,即 0,1,2,3,4,5,6,7,8,9
range(5, 10) # 创建一个从5-9的5个整数的序列,即 5,6,7,8,9

我们经常会把 range 和 for 循环结合起来使用,比如

for i in range(5):
    print(i)

这样就可以用非常简洁的代码执行一定次数的循环。

跳出循环

循环中的代码块会不停的执行,直到条件判断为假,但有的时候,我们想提前结束,应该怎么办呢?我们可以使用 break 跳出循环,如下

for i in range(6):
    print(i)
    if i == 3:
        break

上面的代码中,我们依次遍历0到5这6个整数,但是当遍历到3的时候,我们使用 break 跳出循环,循环就此停止,不再往下执行了,也就说后面的4和5这两个整数不会被遍历到了,因为在遍历到之前,我们已经跳出了循环,所以上面的代码会输出

0
1
2
3

强制进入下一次循环

有的时候,在执行循环的时候,当满足一定的条件时,我们想跳过剩下的代码,直接进入下一次循环,这时我们可以使用 continue 强制进入下一次循环,如下

for i in range(6):
    if i < 3:
        continue
    print(i)

上面的代码中,我们依次遍历0到5这6个数字,但是当遍历的数字小于3的时候,我们不想打印出来,所以直接用 continue 跳过后面的代码,进入下一次遍历。这段代码输出的结果如下

3
4
5

重温列表推导式

前面我们提到过列表推导式,列表推导式其实类似 for 循环,比如

[x**2 for x in range(10)]

这段代码的含义是对于0-9这10个整数,计算它们的平方。所以结果是 [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

我们也可以在列表推导式中添加 if 语句,比如

[x**2 for x in range(10) if x % 2 == 0]

这段代码的意思是对于0-9这10个整数,只有当它能被2整除的时候,我们才计算它的平方,所以结果是 [0, 4, 16, 36, 64]

我们也可以添加多层 for,像下面这样

[(x, y) for x in range(3) for y in range(3)]

这段代码中 x 和 y 会分别遍历0-2这3个整数,所以它生成的结果是一个包含9个二元组的列表,如下

[(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]

好了,到目前为止,我们已经学了不少Python的基础知识了,还记得最开始的一行代码画爱心的例子吗?我们现在运用我们已经学过的知识,来动手操练一下。

实操——一行代码画爱心

首先需要知道,爱心曲线有一个公式

(x2+y2−1)3−x2y3=0

在坐标系上画出来是这样的

有了这个公式,我们可以根据这个公式来判断一个点是在爱心的内部还是外部,如果点在爱心内部我们用字母填充,如果点在爱心外部我们用空格填充,通过这样的方式我们打印出爱心的形状。

我们把打印范围限制在60行x60字符的范围內,进一步我们把这个范围划分成60x60个格子,像下面这样

每个格子都有一个坐标。我们的横坐标从-30到30,纵坐标从30到-30。我们要做的就是在这个每个格子里填入一个空格或者Love中的一个字母,让最终的结果看起来是一颗爱心的形状。

我们可以这样做,对于上图中的每一个格子,如果坐标是在爱心外,我们就输出一个空格,如果坐标是在爱心内,就输出Love 4个字母中的一个。我们从第一行开始,对每一个格子输出空格或字母,然后第二行,第三行,直到最后一行。当我们遍历完所有的行之后,我们就完成了所有字符的打印。

我们用 for 循环来实现一下上面的逻辑,代码如下

for y in range(30, -30, -1):
    for x in range(-30, 30):
        if ((x*0.04)**2+(y*0.1)**2-1)**3-(x*0.04)**2*(y*0.1)**3 <= 0: # 套用公式
            # 这里是爱心内部,我们依次输出 Love 4 个字母中的一个,循环反复
            print('Love'[(x-y) % len('Love')], end='')
        else:
            # 这里是爱心外部,我们输出空格
            print(' ', end='')
    print('')

上面的第一层 for 循环遍历所有的行,第二层 for 循环遍历所有的列。

if((x*0.04)**2+(y*0.1)**2-1)**3-(x*0.04)**2*(y*0.1)**3<=0 这一行代码判断点是否在爱心内部。如果是的话,我们打印 Love 4个字母中的一个,如果不是,我们打印一个空格。

执行上面的代码,可以看到我们已经实现我们想要的功能。

接下来,我们简化代码。对于第二层循环,也就是遍历列的操作,我们用列表推导式来简化,如下

for y in range(30, -30, -1):
    print(''.join([('Love'[(x-y) % len('Love')] if ((x*0.04)**2+(y*0.1)**2-1)**3-(x*0.04)**2*(y*0.1)**3 <= 0 else ' ') for x in range(-30, 30)]))

上面,对于某一行,我们用列表推导式生成这一行所有的字符,然后用 ''.join() 把它们拼接到一起。

我们进一步简化,把第一层循环,也就是对于行的遍历也用列表推导式来简化,如下

print('\n'.join([''.join([('Love'[(x-y) % len('Love')] if ((x*0.04)**2+(y*0.1)**2-1)**3-(x*0.04)**2*(y*0.1)**3 <= 0 else ' ') for x in range(-30, 30)]) for y in range(30, -30, -1)]))

我们用另一个列表推导式生成所有行的内容,然后用 '\n'.join() 把这些行拼接到一起。这样,我们就完成了用一行代码打印爱心的程序。是不是很酷!

以上就是这一节的全部内容。这一节我们介绍了 Python 中各种各样的语句,这些都是 Python 的基本功,在学习过程中,我们要多加练习,熟练掌握它们。下一节我们将介绍函数。

函数

什么是函数呢?函数是一段执行特定逻辑的程序,可以接受参数也可以不接受参数,可以返回值,也可以不返回值。

使用函数

使用函数非常简单,我们在前面看到的 print("hello") 就是一个使用函数的例子。print 是 Python 中的一个内置函数,我们可以直接使用。

如果要使用在模块中的函数,我们首先要把模块 import 进来,像下面这样

import math
math.sqrt(2)

自定义函数

在 Python 中我们可以自定义函数,自定义函数使用关键 def ,像下面这样

def fibs(num):
    fibs = []
    for i in range(num):
        if i == 0:
            fibs.append(0)
        elif i == 1:
            fibs.append(1)
        else:
            fibs.append(fibs[-2] + fibs[-1])
    return fibs

上面的 fibs 是我们自定义的一个函数,它的作用是计算斐波那契数列的前 num 项。fibs 是函数名,fibs 后面的括号里是函数的参数。这里我们的 fibs 函数接受一个参数 num。从 fibs = [] 这一句开始,一直到最后,都是我们函数的主体。最后一行 return fibs 是从函数返回值,我们这里返回的是 fibs 这个列表。

当我们定义了上面的函数后,我们就可以使用这个函数。比如,我们要计算斐波那契数列的前5项,我们可以这么做

fibs(5) # 结果 [0, 1, 1, 2, 3]

函数参数

前面提到到,函数可以接受参数也可以不接受参数。下面是一个不接受参数的例子

def print_hello():
    print("hello")

这里 def print_hello() 表示函数不接受任何参数。

函数也可以接受列表或字典作为参数。对于这两种情况,我们下面各举一个例子来说明。

函数接受列表作为参数

def calc_sum(numbers):
    result = 0
    for i in numbers:
        result += i
    return result
calc_sum([1,2,3])

这里的 calc_sum 接受一个列表 numbers 作为参数,并且计算 numbers 列表中所有元素的总和。

函数接受字典作为参数

words = {"the": 10, "you": 5, "name":1}
def count_words(words):
    result = 0
    for k, v in words.items():
        result += v
    return result
count_words(words)

这里 words 是一个字典,它的内容是一些单词和它们出现的次数。 count_words 接受 words 作为参数,并且计算所有单词出现的总次数。

我们前面看到的参数都是位置参数,调用函数的时候,传递的参数是根据位置来跟函数定义里的参数表匹配的。我们来看一个多参数的例子

def print_person(name, age):
    message = "{} is {} year-old".format(name, age)
    print(message)

上面的 print_person 接受2个参数,在调用的时候我们这么写

print_person("john", 27)

就是通过位置参数来调用,因为 "john" 出现在第一个参数的位置,所以它被赋给 name,27 出现在第二个参数的位置,所以它被赋给 age。

Python 中还有一种传参的方式叫做关键字参数,它是通过名字来跟函数定义里的参数表匹配的。对于上面的 print_person 函数,使用关键字参数调用我们可以这么做

print_person(name="john", age=27)

因为我们指定了名字,所以关键字参数不一定要按照函数定义里的顺序出现,比如下面这样也是合法的

print_person(age=27, name="john")

我们在自定义函数的时候,可以给函数的参数设定一个默认值,比如像下面这样

def print_person(name="jack", age=28):
    message = "{} is {} year-old".format(name, age)
    print(message)

我们给 name 设了个默认值 "jack",给 age 设了个默认值28。设了默认值之后,我们在调用的时候就可以不传这个参数。比如上面的函数,在调用的时候可以不传 name ,也可以不传 age,像这样

print_person() # 输出 jack is 28 year-old
print_person(name="henry") # 输出 henry is 28 year-old

递归

递归是程序设计中一个很重要的概念,简单的讲,递归就是函数自身调用自身。我们来看一个例子

def fib(n):
    if n == 0:
        return 0
    elif n == 1:
        return 1
    else:
        return fib(n-1) + fib(n-2)

上面这个函数 fib 是计算斐波那契数列的第 n 项。我们看到函数主体中有一段:fib(n-1)+ fib(n-2),这个就是递归。我们知道,斐波那契数列的第 n 项是前两项之和,所以这里我们用 fib(n-1) + fib(n-2) 来计算第 n 项的值。

匿名函数

Python 中的 lambda 表达式可以实现匿名函数,比如像这样

lambda x: x**2 * 3.14

这样我们就定义了一个匿名函数,这个函数没有名字。lambda 后面的 x 是这个函数的参数,冒号后面的是函数的主体。我们可以发现这段代码的功能其实是计算圆面积。

那么问题来了,匿名函数没有名字,它是怎么被调用的呢?其实匿名函数一般是作为参数传入其它函数中的,比如像 filter,map,reduce 这些函数会接受一个函数作为参数,这时用匿名函数就可以让代码变得非常简洁。

好,以上就是本节的全部内容。下一节我们讲一下类。

类是对现实世界中的事物或情景的抽象。通过类创建出来的实例叫做对象。在定义类时,我们定义这一类对象共有的通用行为,然后创建对象的时候,每个对象都自动具备了这种行为。

自定义类

下面是一个自定义类的例子

class Person:
    # __init__是一个特殊的方法,每次创建新实例,Python都会自动运行它
    # 注意,开头和末尾都有两个下划线
    # 参数self代表实例本身,实例化的时候会自动传递
    def __init__(self, name, age):
        self.name = name
        self.age = age
        
    def get_name(self):
        return self.name
    
    def set_age(self, age):
        self.age = age
        
    def increment_age(self, delta):
        self.age += delta
        
    def greet(self):
        print("Hello, I'm {}. I am {} year-old".format(self.name, self.age))

上面定义了一个 Person 的类,这个类可以类比现实生活中的人。我们现实生活中的人有名字,有年龄,所以这个类定义了一系列的和人有关的属性和方法,比如 name, age 这是属性,get_name, set_age, increment_age, greet 这些是方法。

需要注意的是,__init__ 方法是一个初始化的函数,在创建对象的时候,它会设置对象的初始值。

仔细的看上面的几个方法,我们会发现一个有趣的现象,所有方法的第一个参数都是 self,事实上,这个 self 代表的就是这个对象本身。我们访问对象的属性,调用对象的方法都会用到这个 self。

类的实例化

当我们有了上面的类之后,我们就可以用它来创建对象

person = Person("john", 25)

这里我们创建了一个 name="john", age=25 的对象,存在 person 这个变量里。

接下来我们访问对象的属性

print(person.name, person.age) # 输出 john 25

调用对象的方法

person.greet() # 输出 Hello, I'm john. I am 25 year-old

调用方法设置属性值

person.set_age(30)
print(person.age) # 输出 30

类的继承

我们可以通过继承来重用类的属性和方法。比如上面定义的 Person 类已经有了 name 和 age 属性,有了 get_name, set_age, increment_age, greet 这些方法,这里我们再定义一个 Employee 类,Employee 类继承自 Person 类,他们的关系如下图

因为 Employee 类继承了 Person 类,Employee 类自动获得 Person 类的属性和方法,此外,Employee 类还可以定义自己特有的属性和方法,比如这里的 industry 属性和 get_industry 方法。这里的 Person 类称为父类,Employee 类称为子类

Employee 类的定义如下

class Employee(Person):
    def __init__(self, name, age, industry):
        # 调用父类的__init__函数
        # super是一个特殊函数,将父类和子类关联起来
        super().__init__(name, age)
        # industry是属于子类的新属性
        self.industry = industry
    
    # 属于子类的新方法
    def get_industry(self):
        return self.industry

上面的第一行代码 class Employee(Person) 表示定义一个新的类 Employee,它继承自 Person 类,括号中的 Person 表示的是被继承的是 Person 类。

在 __init__ 函数中,我们使用了 super().__init__(name, age) 来初始化 Employee 类的 name 和 age 属性。这里的 super() 是一个特殊的函数,它的作用是将父类和子类关联起来,super().__init__ 会调用父类的 __init__ 方法。因为在父类的 __init__ 方法中,我们已经实现了对 name 和 age 属性的初始化,所以我们这里直接重用父类的方法。除了 name 和 age 这两个属性外,Employee 类还定义了 industry 属性,因为这个属性是 Employee 特有的,所以在 Employee 类的 __init__ 方法中,我们实现对这个属性的初始化。

随后,Employee 类还定义了一个特有的方法 get_industry,用于返回 industry 属性值。

定义了 Employee 类之后,我们可以创建 Employee 对象,如下

employee = Employee("john", 25, "finance") 

这里我们创建了一个 name="john", age=25, industry="finance" 的对象,存在 employee 这个变量里。

接下来我们调用对象的方法

print(employee.get_name()) # 输出 john
print(employee.get_age()) # 输出 25
print(employee.get_industry()) # 输出 finance

注意上面的 get_name 和 get_age 是父类 Person 中定义的方法,Employee 类自动继承了这些方法,get_industry 是属于 Employee 类的新方法。

有时,子类继承了父类的方法后,子类中的方法需要不同的实现,这时我们可以对方法进行重写。比如我们在 Employee 类中对 greet 方法进行重写

class Employee(Person):
    def __init__(self, name, age, industry):
        # 调用父类的__init__函数
        # super是一个特殊函数,将父类和子类关联起来
        super().__init__(name, age)
        # industry是属于子类的新属性
        self.industry = industry
    
    # 属于子类的新方法
    def get_industry(self):
        return self.industry
    
    def greet(self):
        print("{}: {} year-old, working in {}".format(self.name, self.age, self.industry))

我们来创建一个 Employee 对象,并且尝试调用 greet 方法

employee = Employee("john", 25, "finance")
employee.greet()

上面的代码会输出 john: 25 year-old, working in finance ,这里调用的是 Employee 类的 greet 方法,而不是 Person 类的 greet 方法,因为我们在 Employee 类里对 greet 方法进行了重写。

使用模块中的类

前文提到过模块中有函数、变量,事实上模块中还可以包含类。比如 datetime 是一个处理日期时间的模块,它其中包含一个叫 timedelta 的类,这个类用来表示时间差或日期差,这个类在我们对时间或日期做加减运算的时候非常有用。我们可以用如下的方式使用这个类

from datetime import timedelta
print(timedelta)  # 输出 <class 'datetime.timedelta'>
d = timedelta(days=5)
print(d) # 输出 5 days, 0:00:00

上面的第一行代码,我们指定从 datetime 模块中导入 timedelta 这个类。

第二行代码我们打印 timedelta,可以看到它的输出是一个 class 类型,也就是说这是一个类。

随后第三行代码我们使用这个类来实例化一个对象,存到变量 d。这个实例化的对象我们给它设置一个属性 days=5,表示这个时间差是5天。我们可以用一个日期和这个时间差做加减运算,得到一个加5天或减5天的日期。

好,以上就是本节的全部内容。下一节我们介绍一下文件读写。

文件读写

准备工作

首先准备一个文件,在文件中随便输入一些文字,比如 zhihu baidu taobao,将这个文件保存成 words.txt,放在和下面的程序所在的同一个目录里。

打开文件

在 Python 中我们使用 open 函数打开一个文件,比如打开我们刚刚创建的文件

f = open("words.txt")

读取文件

打开文件后,我们可以用 read 方法来读取文件的内容,如下

content = f.read()
print(content)

上面的代码会输出文件的内容。

关闭文件

当文件读取完毕后,我们需要关闭文件。关闭文件使用 close 方法,如下

f.close()

至此,文件的一次读取操作完成。

常用的文件打开模式

上面的例子中我们使用的是读取模式,这也是默认的打开模式,文件打开还支持多种其它模式。我们在 open 函数中指定文件的打开模式。

上面的例子中,open 函数中传入了一个文件名的参数,事实上 open 函数还可以接受一个打开模式的参数,这是一个可选参数,默认值是 "r"。比如我们上面的 f = open("words.txt") 其实相当于 f = open("words.txt", "r"),这里的参数 "r" 代表的就是读取模式。

除了读取模式外,open 函数还支持其它的打开模式,如

w写入模式
a追加模式
b二进制模式(与其他模式结合)
rb二进制模式读取
wb二进制模式写入

下面我们看一下写入模式。

写入内容

我们使用写入模式打开一个文件,就可以对这个文件写入内容,比如

f = open("words.txt", "w")
f.write("hello world\n")
f.close()

我们打开 words.txt, 可以看到,里面的内容变成了 hello world。

也许有人会有疑问,原先的内容呢?

原先的内容被删除了。这是因为使用 w 模式打开文件时,它首先会删除之前的内容,然后的写入操作就像是把内容写入了一个新创建的文件。

那如果要保留原先的内容应该怎么做呢?那我们就要提到追加模式。

追加内容

追加模式是在文件原来的内容后面添加新的内容。参数 "a" 表示追加模式,如下

f = open("words.txt", "a")
f.write("another line\n")
f.close()

打开 words.txt,可以看到,里面内容变成了两行,第一行是原来的 hello world,第二行是我们追加的 another line。因为我们使用了追加模式,所以原先的内容没有被删除,我们追加的内容会添加在原先的内容之后。

使用with语句简化代码

上面的例子中,每次读写文件,我们都要先 open 文件,读写完还要记得 close 文件。事实上,Python 提供了一种简化代码的方法,就是使用 with 语句。下面是使用 with 语句简化后的代码

with open("words.txt", "r") as f:
    content = f.read()
    print(content)

可以看到,使用 with 后,我们就不用再写 close 文件的代码了,因为 with 语句会自动地 close 文件。

好,以上就是关于文件读写的全部内容。下一节我们来看一下异常处理。

异常处理

什么是异常

程序执行期间发生的错误叫作异常。比如,我们知道1除以0是一个非法的运算,所以下面的代码就会引发一个异常

1/0

------- 输出 -------

ZeroDivisionError                         Traceback (most recent call last)
Input In [1], in <cell line: 1>()
----> 1 1/0

ZeroDivisionError: division by zero

上面的异常消息提示我们这里的除数为0。这个异常的类型 ZeroDivisionError 是一个类,用来表示除数为0的异常,这里抛出的是 ZeroDivisionError 类实例化后的一个对象。Python 中的所有异常状态都是由异常类实例化的对象来表示,在遇到错误的时候,会抛出这个异常对象。

捕获异常

我们可以使用 try ... except ... 语句捕获异常。在 try 里面是可能会发生错误的代码,except 用于捕获异常,在except 里是处理异常的代码。举个例子就很清楚了

try:
    x = int(input('Enter the first number: '))
    y = int(input('Enter the second number: ')) 
    print(x/y)
    print("after division")
except ZeroDivisionError:
    print("the second number cannot be zero")

这里 x 和 y 两个整数,他们的值由用户输入,x 和 y 被赋值之后,我们计算 x 除以 y。因为 x 和 y 的值由用户输入,他们可以是任意值,y 可以是 0 也可以不是 0。因为存在 y 等于 0 的可能,除数为 0 会引发异常,所以我们需要捕获这个异常。

我们把可能会出错的代码放在了 try 里面。对于 print(x/y) 这行代码,如果 y 不等于 0,就会输出 x/y 的值,并且 try 里面的代码继续执行,也就是执行 print("after division") 这行。因为没有异常抛出,所以 except 不会捕获到异常,except 子句中的代码 print("the second number cannot be zero") 也就不会被执行。如果 print(x/y) 中 y 等于 0,x/y 就会抛出异常。抛出异常后,这行代码之后的 print("after division") 就不会被执行了,程序的执行直接来到 except ZeroDivisionError 这一行,现在这个异常被这个 except 捕获到了,程序执行 except 中的代码。

上面这段代码运行的时候,我们分别输入 1 和 0,也就是 x = 1, y = 0,会看到如下的输出

the second number cannot be zero

上面,我们的 except 语句指定了要捕获的异常的类型,也就是 ZeroDivisionError 类型的,前文提到,Python 中所有抛出的异常都是对象,自然我们捕获到的也是对象,我们可以把这个对象存到一个变量里,用如下的方式

try:
    x = int(input('Enter the first number: '))
    y = int(input('Enter the second number: ')) 
    print(x/y)
except ZeroDivisionError as e:
    print(e)

这里我们使用关键字 as 把捕获到的异常对象存到变量 e 里,然后我们打印 e 。

上面的例子中,我们只捕获了 ZeroDivisionError 这种类型的错误,也就是除数为0的情况。事实上,我们在获取用户输入的时候,也可能会发生错误。比如用户输入的是一个非数字的值,像 aaa,bbb 这种。对于这种非数字的值,在我们将它转换成数值的时候,程序会抛出一种叫 ValueError 的错误。如果要捕获 ValueError 类型的异常,我们需要在上面的代码中再多加一个 except 语句,如下

try:
    x = int(input('Enter the first number: '))
    y = int(input('Enter the second number: '))
    print(x/y)
except ZeroDivisionError:
    print("the second number cannot be zero")
except ValueError:
    print("input is not number")

我们用两个 except 语句来分别捕获 ZeroDivisionError 类型和 ValueError 类型的错误,使用多个 except 语句可以让我们捕获多种类型的异常。我们运行上面的程序,并且依次输入 aaa,bbb,会看到程序输出

input is not number

这里异常被 except ValueError 这个子句捕获到了,所以这个子句里的代码 print("input is not number") 被执行。

如果要捕获所有类型的异常,我们可以使用 except 不加类型,像下面这样

try:
    x = int(input('Enter the first number: '))
    y = int(input('Enter the second number: ')) 
    print(x/y)
except:
    print("error")

这里只要 try 里面的代码抛出了异常,不论什么类型,都会被 except 捕获到。当我们不确定程序会抛出什么类型的异常时,我们可以使用这种方式。

当 try 里面的代码抛出异常时,程序的执行会被中断,就像我们前面看到的那样。但有些时候不管有没有异常发生,我们都希望能在最后做一些清理工作,这时就会用到 finally 子句。

finally 子句的用法如下

try:
    x = int(input('Enter the first number: '))
    y = int(input('Enter the second number: ')) 
    print(x/y)
finally:
    print("clean up")

这里不管 try 中的代码有没有发生异常,finally 中的代码都会被执行。

好,到目前为止,我们讨论的都是如何捕获异常,那如果我们要在程序中手动引发异常,应该怎么做呢?

引发异常

引发异常使用 raise 语句,比如

raise Exception("this is an exception")

我们这里抛出了一个 Exception 类型的异常,括号里面是这个异常的信息。需要注意的是 Exception 是 Python 中内置的一个类,Python 中几乎所有的异常都是 Exception 的子类。

我们可以在 try 语句中手动抛出异常,如下

has_error = True
try:
    if has_error:
        raise TypeError("some error happens")
except Exception as e:
    print(e)

上面的 TypeError 会被 except 捕获到,因为 TypeError 是 Exception 的子类。

自定义异常

有时 Python 中已经定义好的异常类型不能满足我们的需求,这时我们可以自己定义一个异常类。定义异常类需要继承 Exception 这个类,如下

class MyCustomException(Exception):
    pass

raise MyCustomException

上面我们定义了一个 MyCustomException 的异常类,并且手动引发这个异常。

常见的异常类型

这里罗列了一些 Python 中常见的异常类型以及引发这些异常的代码,这些代码不少也是初学者在刚学 Python 的时候容易犯的错误。对于初学者,理解这些异常发生的原因是非常重要的。

ZeroDivisionError - 除法运算中除数为 0 时引发此异常

1 / 0
------ 输出 ------
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ZeroDivisionError: division by zero

FileNotFoundError - 尝试打开一个不存在的文件时,引发此异常

f = open("some-not-existing-file.txt")
------ 输出 ------
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
FileNotFoundError: [Errno 2] No such file or directory: 'some-not-existing-file.txt'

NameError - 尝试访问一个未声明的变量时,引发此异常

print(abc)
------ 输出 ------
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'abc' is not defined

AttributeError - 当试图访问的对象属性不存在时抛出的异常

a = [1, 2, 3]
print(a.name)
------ 输出 ------
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'list' object has no attribute 'name'

IndexError - 索引超出序列范围时引发此异常

a = [1, 2, 3]
print(a[3])
------ 输出 ------
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: list index out of range

KeyError - 字典中查找一个不存在的关键字时引发此异常

person = {"name": "john"}
print(person["age"])
------ 输出 ------
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'age'

TypeError - 不同类型数据之间进行无效操作时引发此异常

"hello" + 123
------ 输出 ------
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can only concatenate str (not "int") to str

ValueError - 传入无效的参数(类型正确但值无效)时引发此异常

int("abc")
------ 输出 ------
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 10: 'abc'

IndentationError - 缩进错误时引发此异常

a = 1
if a > 0:
print("good")
------ 输出 ------
  File "<stdin>", line 2
    print("good")
        ^
IndentationError: expected an indented block

SyntaxError - 出现Python语法错误时,引发此异常

a = 1
while a < 1
    print("good")
    a += 1
------ 输出 ------
  File "<stdin>", line 1
    while a < 1
              ^
SyntaxError: invalid syntax

好,以上就是异常处理的全部内容。

总结

关于 Python 基础的内容就全部讲完了,掌握这些内容基本上算是入门 Python 了,当然要熟练掌握 Python 还离不开亲自动手实践。建议多操练,多写代码,这样才能熟能生巧。

【python学习】
学Python的伙伴,欢迎加入新的交流【君羊】:572077127
一起探讨编程知识,成为大神,群里还有软件安装包,实战案例、学习资料

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值