name = "xiao hong" # name 就是一个变量
name_student = "xiao hong" # name_student 也是一个变量
2name = "xiao hong" # 是错误的写法,数字不能放在变量的开头
在Python中,字符串就是一串用引号括起来的字符串,注意单引号、双引号都可以!
"This is string" # 双引号、单引号都可以表示一个字符串
'This is string'
操作符 | 解释 |
---|---|
title() | 将单词首字母变为大写 |
upper() | 将单词变为大写 |
lower() | 将单词变为小写 |
name = "xiao hong"
print(name.title())
print(name.upper())
print(name.lower())
输出:
Xiao Hong
XIAO HONG
xiao hong
有时,我们需要将变量赋值给字符串,python中具体操作是:str = f"{变量名}" 或 str = “{}”.format(变量名)
举例看看就懂:
name_1 = "xiao hong" # name_1 是变量
name_2 = "li gang" # name_2 是变量
student = f"{name_1} and {name_2} are students" # student 中的字符串包含上面两个变量的值
print(student)
输出:
xiao hong and li gang are students
或者:
student = "{} and {} are students".format(name_1, name_2)
print(student)
输出:
xiao hong and li gang are students
制表符:\t
print("\tpython") # 输出字符串会缩进
输出:
python
换行符:\n
print("\npython") # 输出字符串会在下一行输出
输出:
python
制表符、换行符一起使用:
print("\npython") # 输出字符串会在下一行缩进输出
输出:
python
对于程序来说,"python"和"python "是不一样的,因为后者中包含空格,但有些场景我们认为他们是一致的,这时我们就应该将他们做一些处理,删除其中的空格!
操作符 | 解释 |
---|---|
strip() | 删除左右两边的空格 |
rstrip() | 删除右边的空格 |
lstrip() | 删除左边的空格 |
举例看看:
language = " python " # 左右都有空格
print(language.strip()) # 删除左右空格
print(language.rstrip()) # 删除右边空格
print(language.lstrip()) # 删除左边空格
输出:
python
python
python
python中整数的操作:(+)加、(-)减、(*)乘、(/)除、(//)整除、(**)乘方、(%)取余
具体举例看看就懂:
print(1 + 2) # 加
print(2 - 1) # 减
print(2 * 3) # 乘
print(3 / 2) # 除
print(3 // 2) # 整除:3除以2是1.5,再对1.5取整就是1
print(3 ** 2) # 乘方: 这里是3的2次方。同理(3 ** 4)表示:3的4次方,结果是81
print(3 % 2) # 取余:3除以2,余数是1
输出:
3
1
6
1.5
1
9
1
注意:空格不影响上面的计算表达式
带小数点的数称为浮点数,浮点数的操作和上面一致!注意:任意两个数相除都是浮点数,即是这两个数可以整除,举例看看:
print(4 / 2) # 可以整除,结果也是浮点数!
输出:
2.0
当数字很大时,可以使用下划线,让数字显示的更加清晰明了:
number = 14_000_000_000 # 140亿,这样表示很清晰明了,其中下划线不影响数字的大小、存储等!
print(number) # 打印时,是不会显示下划线的
输出:
14000000000
注意:
1_000 和 10_00 大小是一样的
常量即在程序运行中大小保持不变。一般使用全部大写来表示常量:
NUMBER = 100 # 一般用这种全部大写的来表示常量!
列表是由一系列按特定顺序排列的元素组成!在python中用 [] 表示列表,其中各元素由逗号隔开。
举例看看:
name = ["xiao hong", "li gang"] # name 是一个列表,包含两个元素,元素之间由逗号隔开
print(name)
输出:
['xiao hong', 'li gang']
列表中的元素是有序的,我们可以根据元素的位置(索引)找到具体的元素!如:列表名[索引]
注意:python中的索引从0开始,即0表示第一个元素
举例看看就懂:
name = ["xiao hong", "li gang"] # 列表
print(name[0]) # 返回列表第一个元素,索引从0开始
print(name[1]) # 返回列表第二个元素
输出:
xiao hong
li gang
如何获取最后的元素呢?
name = ["xiao hong", "li gang"]
print(name[-1]) # -1 表示访问列表中最后一个元素
输出:
li gang
同理,倒数第二的元素用-2表示,以此类推!
我们对于获取的元素可以进一步操作,如:
name = ["xiao hong", "li gang"]
print(name[0].title()) # 将第一个元素变为首字母大写的字符串
输出:
Xiao Hong
name = ["xiao hong", "li gang"] # 列表
result = f"{name[0]} is a good student" # 将列表元素放入字符串中!
print(result)
输出:
xiao hong is a good student
我们一般会对创建的列表进行改动,来符合我们想要的列表,包括对列表元素的修改、添加、删除等操作!
修改列表中某元素的操作:列表名[索引] = 新值
举例看看就懂:
name = ["xiao hong", "li gang"] # 原始列表
print(name)
name[0] = "da zhuang" # 修改第一个元素
print(name)
输出:
['xiao hong', 'li gang']
['da zhuang', 'li gang']
我们不仅可以修改第一个元素,同理可以修改任意位置的元素!
有时我们需要在列表中添加新的元素,具体操作如下:
name = ["xiao hong", "li gang"] # 原始列表
print(name)
name.append("da zhuang") # 添加元素
print(name)
输出:
['xiao hong', 'li gang']
['xiao hong', 'li gang', 'da zhuang']
name = ["xiao hong", "li gang"] # 原始列表
print(name)
name.insert(1, "da zhaung") # 在第一个位置插入“da zhuang”
print(name)
输出:
['xiao hong', 'li gang']
['xiao hong', 'da zhaung', 'li gang']
对于不同场景,我们删除元素的方法是不一样的,具体分为:
name = ["xiao hong", "li gang", "da zhuang"] # 原始列表
print(name)
del name[2] # 删除第三个元素
print(name)
输出:
['xiao hong', 'li gang', 'da zhuang']
['xiao hong', 'li gang']
name = ["xiao hong", "li gang", "da zhuang"] # 原始列表
print(name)
name.remove("da zhuang") # 删除第三个元素
print(name)
输出:
['xiao hong', 'li gang', 'da zhuang']
['xiao hong', 'li gang']
若列表中出现多个相同元素,remove操作只能删除第一个指定的元素!
以上操作,删除元素后,被删除的元素就找不到了,无法再去访问了,而有时我们需要刚刚删除的元素,这时我们可以弹出要删除的元素
name = ["xiao hong", "li gang", "da zhuang"] # 原始列表
print(name)
item = name.pop() # 默认弹出最后一个元素,我们也可以指定索引来弹出具体位置的元素
print(name)
print(item)
输出:
['xiao hong', 'li gang', 'da zhuang']
['xiao hong', 'li gang']
li gang
通过上面的操作发现,pop 和 del 的作用基本一致,但是del删除元素后就不能再访问该元素了,而pop可以再访问这个元素!
当我们创建好一个列表时!其中元素的顺序可能不是我们想要的,我们可能想升序或降序元素值,那么具体如何操作呢!
我们可以使用sort()方法对列表进行排序:列表名.sort()
具体举例看看就懂:
age = [23, 18, 19, 20, 22, 18, 20] # 原始列表
print(age)
age.sort() # 排序,默认升序
print(age)
age.sort(reverse=True) # 降序
print(age)
输出:
[23, 18, 19, 20, 22, 18, 20]
[18, 18, 19, 20, 20, 22, 23]
[23, 22, 20, 20, 19, 18, 18]
如果我们在排序后,还要保留以前的列表,就应该使用sorted()方法:sorted(列表名)
age = [23, 18, 19, 20, 22, 18, 20] # 原始列表
print(age)
print(sorted(age)) # 升序后的临时列表
print(sorted(age, reverse=True)) # 降序后的临时列表
print(age) # 原始列表,没有改变
输出:
[23, 18, 19, 20, 22, 18, 20]
[18, 18, 19, 20, 20, 22, 23]
[23, 22, 20, 20, 19, 18, 18]
[23, 18, 19, 20, 22, 18, 20]
一般使用函数 len() 获取列表长度,具体看看:
age = [23, 18, 19, 20, 22, 18, 20]
print(len(age))
输出:
7
第三章,我们学习了如何创建列表、以及对列表中元素的简单操作,如果我们要对列表中每个元素进行某个操作,那么就需要遍历列表,具体看看:
我们可以使用for循环来不断遍历列表中的元素,举例看看:
names = ["xiao hong", "li gang", "da zhuang"]
for i in names: # for循环会不断遍历列表中的元素,并赋值给变量i
print(i)
输出:
xiao hong
li gang
da zhuang
上述代码中的 i 是我们指定的临时变量,也可以写成其他任意值,一般应该具有一定的指代意义,所以最合适的代码如下:
names = ["xiao hong", "li gang", "da zhuang"]
for name in names:
print(name)
输出:
xiao hong
li gang
da zhuang
我们可以在打印同学名字时,给他们加上一定的信息,如每位同学都是好学生,我们只需要在循环中不断的输出每位同学都是好学校即可!
names = ["xiao hong", "li gang", "da zhuang"] # 列表
for name in names: # 循环
print(f"{name} is a good student") # 缩进,表示在for的循环体内
输出:
xiao hong is a good student
li gang is a good student
da zhuang is a good student
我们还可以在for循环结束后,做一些操作
names = ["xiao hong", "li gang", "da zhuang"] # 列表
for name in names: # 循环
print(f"{name} is a good student") # 缩进,表示在for的循环体内
print("everyone is a good student") # 在循环体外!
输出:
xiao hong is a good student
li gang is a good student
da zhuang is a good student
everyone is a good student
python中主要以缩进来划分模块,如上面例子,在for循环语句之后,缩进的表示循环体,没有缩进的表示不是for循环体的!
注意:for循环后面要加冒号(:),表示下面的语句是循环体!
上面我们创建了字符串列表,但很多场景下,我们需要一组元素为数字的列表,像班级学生年龄、一年的温度等等,这些都可以用列表来存储!
对于连续的一段数,我们可以用 range()函数 来生成,如:
for value in range(1, 3):
print(value)
输出:
1
2
range()函数 括号内的数是 左闭右开 的,即从括号左边数开始,直到右边界,但不包含右边界!我们再看个例子:
for value in range(3):
print(value)
输出:
0
1
2
上面的数,从0开始到2,不包括3!
我们可以将range()函数创建的数直接传入list()函数中,如下:
numbers = list(range(1, 6)) # 将range生成的一系列数直接传入list中,生成列表
print(numbers)
输出:
[1, 2, 3, 4, 5]
当然我们也可以先申请一个空列表,再利用for循环不断的添加元素,具体如下:
numbers = [] # 先申请一个空列表
for value in range(1, 6): # 循环
numbers.append(value) # 添加元素到列表中,append函数上面我们提到过!
print(numbers)
输出:
[1, 2, 3, 4, 5]
当然我们再添加元素时,也可以对元素进行一些操作:
numbers = [] # 先申请一个空列表
for value in range(1, 6): # 循环
numbers.append(value ** 2) # 将元素平方,再添加到列表中!
print(numbers)
输出:
[1, 4, 9, 16, 25]
操作 | 解释 |
---|---|
min() | 返回最小值 |
max() | 返回最大值 |
sum() | 返回列表元素之和 |
举例看看:
numbers = [1, 2, 3, 4, 5] # 列表
print(min(numbers)) # 打印最小值
print(max(numbers)) # 打印最大值
print(sum(numbers)) # 打印列表元素之和
输出:
1
5
15
上述生成期望列表,一般需要多行代码,采用列表解析式我们可以一行代码搞定,具体为:列表名 = [表达式 循环体 条件] ,具体我们举例看看就懂。
假如我们想要1 - 10之间的偶数:
numbers = [value for value in range(1, 11) if value % 2 == 0]
print(numbers)
输出:
[2, 4, 6, 8, 10]
上述代码中:
上面我们提到了如何用for循环对列表所有元素进行操作,但有时只需要对列表中的部分进行操作,这时就可以用列表的切片操作!
我将通过举例,来解释切片的具体操作:列表名[左索引 :右索引]
注意:
下面五个例子包括了所有的切片操作:
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] # 原始列表
print(numbers[1: 5]) # 取索引1-5的元素
print(numbers[:5]) # 从头开始,一直到索引为5的元素
print(numbers[5:]) # 从索引为5的元素开始,一直到结束
print(numbers[:]) # 从头到尾,即取所有元素!
print(numbers[1:10:2]) # 取索引1-10的元素,步长为2来取数
输出:
[2, 3, 4, 5]
[1, 2, 3, 4, 5]
[6, 7, 8, 9, 10]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
[2, 4, 6, 8, 10]
上面我们还提到过 负号(-) 的使用,表示倒数,如:
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] # 原始列表
print(numbers[:-2]) # 从头开始,到倒数第2个元素结束
输出:
[1, 2, 3, 4, 5, 6, 7, 8]
上面我们对列表所有元素进行了遍历,当然可以对切片的列表进行遍历,我们举例看看:
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] # 原始列表
for value in numbers[5:]: # 循环遍历切片后的列表
print(value) # 不断打印出来
输出:
6
7
8
9
10
列表的复制有两种方式:
上述两种方式有什么不同呢?我们举例看看就懂:
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] # 原始列表
numbers_copy = numbers[:] # 复制原始列表中的元素到新列表
print(numbers)
print(numbers_copy)
输出:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
我们对两个列表再进行操作看看:
numbers.append(100) # 原始列表添加元素100
print(numbers)
print(numbers_copy)
输出:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
通过方式一,原始列表添加元素后,新列表不变,说明原始列表和新列表是两个列表,即深拷贝
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] # 原始列表
numbers_copy = numbers # 指定新列表名,指向原始列表
print(numbers)
print(numbers_copy)
输出:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
numbers.append(100) # 原始列表添加元素100
print(numbers)
print(numbers_copy)
输出:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100]
通过方式二,原始列表添加元素后,新列表也添了元素,说明原始列表和新列表其实是一个列表!,即浅拷贝
列表适用于在程序运行中,其元素不断发生改变的场景,但有时我们也需要创建一系列值不变的列表,而元素不可变的列表就叫元组
元组和列表很像,元组是用 ()圆括号 定义的!我们可以向列表中元素的访问一样,去访问元组中的元素!
我们举例看看就懂:
dimensions = (100, 200) # 元组
print(dimensions[0]) # 打印第一个元素
输出:
100
# 元素的值是不能改变!改变的话,就会报错!
dimensions = (100, 200) # 元组
dimensions[0] = 300 # 改变第一个元素的值
输出:
TypeError: 'tuple' object does not support item assignment
元组的遍历和列表的遍历一样,我们举例看看:
dimensions = (100, 200) # 元组
for value in dimensions: # 循环,遍历
print(value) # 打印
输出:
100
200
虽然元组中元素是不能修改的,但是元组变量是可以修改,我们举例看看就懂:
dimensions = (100, 200) # 元组
print(dimensions)
dimensions = (300, 400) # 给元组变量重新赋值新的元组
print(dimensions)
输出:
(100, 200)
(300, 400)
前面我们学会列表、元组的创建,以及其遍历方式,但有时我们在遍历时,只需要其中一部分数据,如一组数中的偶数;这时,我们就应该不断对列表中元素进行判断!
numbers = [1, 2, 3, 4, 5] # 原始列表
for value in numbers: # 循环
if value % 2 == 0: # 当除以2余数为0时,即偶数时,打印
print(value)
输出:
2
4
if 语句的核心就是一个值为 True 或 False 的表达式,当为True时,继续往下走,否则跳出!
一般用 == 来检查左右两边是否相等!
numbers = [1, 2, 3, 4, 5]
for value in numbers:
if value == 2: # 等于 2,打印
print(value)
对于字符串检查相等时,“A” 和 “a”是不一样,如果我们在判断时,想忽略大小写的影响,我们可以用 lower()函数 ,对元素统一变为小写后比较!
names = ["Xiao Hong", "Li Gang", "Da Zhuang"]
for name in names:
if name.lower() == "li gang": # 若元素统一小写后
print(name)
输出:
Li Gang
一般用 != 来检查左右两边是否不相等!
numbers = [1, 2, 3, 4, 5]
for value in numbers:
if value != 2:
print(value)
输出:
1
3
4
5
有一系列的比较数值大小的符号,如: >、<、>=、<=、==,和上面的同理!
有时我们需要同时满足好几个条件,才能得到我们想要的数据,这时可以用 and 和 or来连接这些条件!
numbers = [1, 2, 3, 4, 5]
for value in numbers:
if value > 2 and value < 5: # 同时满足这两个条件的, 就打印出来
print(value)
输出:
3
4
numbers = [1, 2, 3, 4, 5]
for value in numbers:
if value < 2 or value > 4: # 满足任意一个条件的,就打印出来
print(value)
numbers = [1, 2, 3, 4, 5]
for value in numbers:
if (value < 2 or value > 3) and value % 2 == 0: # 满足圆括号内的和括号外的所有条件,就打印
print(value)
我们用 in 来检查元素是否在列表中,举例看看:
numbers = [1, 2, 3, 4, 5]
print(2 in numbers)
输出:
True
我们用 not in 来检查元素是否不在列表中,举例看看:
numbers = [1, 2, 3, 4, 5]
print(8 not in numbers)
输出:
True
布尔表达式和条件测试表达式一样,只是布尔表达式结果要么是True,要么是False。
game_start = True
前面举例中,已经可以看出if语句的写法,其中最简单的为:
if 条件表达式: # 如果条件测试满足,则执行下面缩进的代码
do something
例如:
age = 100
if age > 80: # 满足条件,才执行下面缩进的语句!
print("This is a man who lived a long life")
输出:
This is a man who lived a long life
对于 if-else 语句,一般在条件满足时,执行 if 语句后面的操作;条件不满足时,执行else后的操作。
if 条件表达式:
某些操作
else:
另外一些操作
例如:
age = 50
if age > 80:
print("This is a man who lived a long life")
else:
print("…………………………")
输出:
…………………………
我们一般会检查超过两个情形的条件,这时就需要使用 if - elif - else结构 ,python会依次检查每个条件测试语句,测试通过,就会执行其后面的语句,并跳过其他的测试!
age = 12
if age < 4: # 年龄 < 4岁, 门票免费
print("Your admission cost is 0 yuan")
elif age < 18: # 4 <= 年龄 < 18,门票50元
print("Your admission cost is 50 yuan")
else: # 年龄 >= 18,门票100元
print("Your admission cost is 100 yuan")
输出:
Your admission cost is 50 yuan
上面的例子中,先检查 if 语句中的表达式是否满足,发现不满足;继续看elif中的语句是否满足,发现满足,就执行其后面的操作(打印);由于elif语句满足了,就不再往下看了,即不会再执行else中的操作。
我们可以根据需要,使用多个elif来划分我们的情况,举例如下:
age = 50
if age < 4:
print("Your admission cost is 0 yuan")
elif age < 15:
print("Your admission cost is 20 yuan")
elif age < 40:
print("Your admission cost is 50 yuan")
else:
print("Your admission cost is 60 yuan")
输出:
Your admission cost is 60 yuan
if-else结构中,else并不是必须存在的,我们也可以将其忽略的,例如:
names = ["Xiao Hong", "Li Gang", "Da Zhuang"]
for name in names:
if name.lower() == "li gang": # 满足条件,则执行下面操作(打印),对于不满足条件的,我们不做处理!
print(name)
输出:
Li Gang
if - elif - else结构,仅仅适用于测试一个条件是否满足,若满足条件,python会跳过剩下的测试。但有时我们需要测试多个条件,这时怎么办呢?
我们可以使用多个 if 语句来做,具体我们举例看看:
information = ["order", "noodles", "rice"]
if "order" in information: # 这三个测试条件都会进行检查
print("The customer has placed an order")
if "noodles" in information:
print("customers eat noodles!")
if "rice" in information:
print("customers eat rice!")
输出:
The customer has placed an order
customers eat noodles!
customers eat rice!
总结:
可以对列表中的元素使用 if 语句,对特定值做动态变化,有助于列表的管理等等!
age = [12, 10, 13, 1200, 14] # 初中某班学习年龄的列表数据
for value in age: # 循环遍历
if 10 < value < 20: # 若在10-20岁之间,正常
print("True")
else: # 范围之外的,不正常
print("False")
输出:
True
True
True
False
True
age = [12, 10, 13, 14] # 列表
if age: # 若列表存在, 则遍历打印
for value in age:
print(value)
else: # 若列表不存在,则打印 “数据不存在”
print("The data doesn't exist!")
输出:
12
10
13
14
在编程习惯,我们一般会在一些地方加空格,来使得代码看起来更加明朗,例如:
if age < 4: #这个要比下面的好!
if age<4:
和列表不同,python中的字典可以表示的含义更加的广泛!例如我们可以创建一个表示人的字典,并可以在其中存储人的姓名、年龄、职业等等信息!
字典是以键值对存储的,例如 字典名 = {键:值,键:值,等等}
假如我们要存储一个人的姓名和年龄,我们试着用字典来表示:
# 字典 information 中存储了姓名和年龄的信息!
information = {
"name": "da zhuang", "age": 18}
print(information["name"])
print(information["age"])
输出:
da zhuang
18
在python中,字典是一系列 键值对组成 的。每个键都有一个值对应,我们可以使用键来访问对应的值。与键对应的 值可以使数、字符串、列表、字典 都可以!
字典用 {} 来表示,键和值用冒号分隔,键值对之间用逗号隔开!
如果想要获取某个键所对应的值,我们可以用: 字典名[键名]
information = {
"name": "da zhuang", "age": 18}
print(information["name"]) # 获取键name对应的值
print(information["age"]) # 获取键age对应的值
输出:
da zhuang
18
字典是动态结构,对于建好的字典,我们可以继续往里面添加键值对,方法为: 字典名[新的键名] = 新的值 , 举例看看就懂:
information = {
"name": "da zhuang", "age": 18}
print(information)
information['height'] = 165
print(information)
输出:
{
'name': 'da zhuang', 'age': 18}
{
'name': 'da zhuang', 'age': 18, 'height': 165}
很多时候,我们都会先创建一个空的字典,再往里面添加键值对,来达到我们最终要的字典
information = {
} # 创建一个空字典
information["name"] = "da zhuang" # 添加键值对
information["age"] = 18 # 添加键值对
print(information)
输出:
{
'name': 'da zhuang', 'age': 18}
对于建立好的字典,我们要修改某个键对应的值时,只需要重新赋值即可:字典名[键] = 新值
information = {
'name': 'da zhuang', 'age': 18}
information["age"] = 20 # 我们对键age的值,进行修改
print(information)
输出:
{
'name': 'da zhuang', 'age': 20}
对于不要的键值对,我们直接用 del 来删除:del 字典名[键]
information = {
'name': 'da zhuang', 'age': 18} # 原始字典
del information["age"] # 删除键值对
print(information)
输出:
{
'name': 'da zhuang'}
删除后的键值对,永远消失,不会再出现的!
上面我们提到了,可以使用字典中的键来访问其对应的值,若字典中没有这个键,就会报错,我们举例看看:
information = {
'name': 'da zhuang', 'age': 18}
print(information["color"]) # 字典中没有键color,就会报错!
输出:
Traceback (most recent call last):
File "C:/Users/Administrator/PycharmProjects/LeetCode/venv/1.py", line 3, in <module>
print(information["color"])
KeyError: 'color'
为了防止报错,我们使用 get()函数 来访问键对应的值:值 = 字典 . get(键,默认值) ! 若字典中的键存在,直接返回其对应的值。若没有没有该键,则直接返回默认值!
information = {
'name': 'da zhuang', 'age': 18} # 字典
age_value = information.get("age") # 键“age”存在,直接返回其值
color_value = information.get("color", "No Value!") # 键“color”不存在,返回默认值(自己定义),不会报错!!!
print(age_value)
print(color_value)
输出:
18
No Value!
若我们不知道字典中某个键是否存在,就应该用get()函数!
get(键,默认值):若其中默认值没有定义,并且该键不存在,python会默认返回None!
字典中存在的键值对可能会很多,我们有时需要对其进行遍历,而字典的遍历方式有多种:键的遍历、值的遍历、键值对的遍历!
information = {
'name': 'da zhuang', 'age': 18} # 字典
for key, value in information.items(): # 遍历键值对
print("key: ",key)
print("value: ", value)
输出:
key: name
value: da zhuang
key: age
value: 18
仅仅访问字典中所以的键: 字典名 . keys()
information = {
"1":"aa", "2":"dhe"} # 字典
print(information.keys()) # 返回所有的键
输出:
dict_keys(['1', '2'])
information = {
'name': 'da zhuang', 'age': 18}
for key in information.keys():
print("key: ",key)
输出:
key: name
key: age
可以使用sorted()函数
information = {
'name': 'da zhuang', 'age': 18}
for key in sorted(information.keys()): # 对键排序(升序)
print("key: ",key)
输出:
key: age
key: name
information = {
'name': 'da zhuang', 'age': 18}
for key in sorted(information.keys(), reverse=True): # 对键排序(降序)
print("key: ",key)
输出:
key: name
key: age
仅仅访问字典中的所有值:字典名 . values()
information = {
'name': 'da zhuang', 'age': 18}
print(information.values())
输出:
dict_values(['da zhuang', 18])
information = {
'name': 'da zhuang', 'age': 18}
for v in information.values():
print("value: ", v)
输出:
value: da zhuang
value: 18
为了表示更多的信息,有时我们需要将字典存储在列表中、将列表作为值存储到字典中,这种方式就叫做 嵌套 。
将字典存储到列表中!
student_1 = {
'name': 'da zhuang', 'age': 18} # 学生1的信息
student_2 = {
'name': 'li ming', 'age': 19} # 学生2的信息
student_3 = {
'name': 'xiao hong', 'age': 18} # 学生3的信息
student = [student_1, student_2, student_3] # 将学生的信息放一起
print(student)
输出:
[{
'name': 'da zhuang', 'age': 18}, {
'name': 'li ming', 'age': 19}, {
'name': 'xiao hong', 'age': 18}]
可以将列表作为值,存储到字典中
student = {
'name': ["da zhuang", 'li ming', 'xiao hong'], 'age': [18, 19, 18]}
print(student) # 整体字典
print(student["name"]) # 键name对应的值
输出:
{
'name': ['da zhuang', 'li ming', 'xiao hong'], 'age': [18, 19, 18]}
['da zhuang', 'li ming', 'xiao hong']
可以将字典作为值,存储到另一个字典中
li_ming = {
'name': "da zhuang", 'age': 18} # 字典
xiao_hong = {
'name': "da lao", 'age': 20} # 字典
Class = {
"user1": li_ming, "user2": xiao_hong} # 字典嵌套字典
print(li_ming)
print(xiao_hong)
print(Class)
输出:
{
'name': 'da zhuang', 'age': 18}
{
'name': 'da lao', 'age': 20}
{
'user1': {
'name': 'da zhuang', 'age': 18}, 'user2': {
'name': 'da lao', 'age': 20}}
函数input()会暂停程序,等待用户输入,获取用户的输入后,会赋值给指定的变量,然后执行后面的程序!
input_value = input()
print("information: ", input_value)
输出:
liming # liming 是我们输入的信息
information: liming
通过上面的例子,我们将输入的信息赋值给变量 input_value ,然后打印这个变量!
我们可以在input()函数中加上,用户输入信息的提示符。如:
input_value = input("please enter your name:") # 括号中是提示信息,让用户输入自己名字, input_value 变量为用户输入信息,不会有提示信息的!
print("hello! ", input_value)
输出:
please enter your name:liming # liming 是我们输入的
hello! liming
对于 input()函数 ,python会将用户的 输入 解读为 字符串 , 我们可以用 int()函数 将字符串转换为数值,
age = int(input("please enter your age:")) # int()将字符串15,变为整型15
if age >= 18:
print("成年人")
else:
print("未成年人")
输出:
please enter your age:15 # 15是我们输入的
未成年人
前面我们提到了for循环,其会遍历集合中的所有元素,而while循环则不断运行,直到指定的条件不满足为止!
我们用while循环实现一个简单的数数问题:
count = 1 # 定义变量
while count <= 5: # 若count <= 5,就一直执行下面的程序
print(count) # 打印count值
count += 1 # count 加一
输出:
1
2
3
4
5
上面程序,一旦count大于5,不满足循环条件,就不会再执行的!
while循环在满足条件时,会一直执行,若需要满足多个条件时,只用一条while检查所有条件会很复杂。
我们可以使用一个变量(标志),来统一所有条件是否都满足,若标志为True,则循环执行,否则跳出!
action = True # 作为标志
while action: # 为True,就一直执行
print("action something!")
我们可以使用 break函数 来停止while循环,不论循环条件是否满足!
count = 12
while count >= 10: # 满足条件,循环
if count < 15: # 满足条件,执行,count自身加一
print("action something!")
count += 1
else: # count 大于等于15,就跳出循环
break
输出:
action something!
action something!
action something!
continue仅仅跳出本次循环,在从头开始循环(若条件满足)
前面提到用for循环来遍历列表中的元素,如果我们想修改列表中的元素时,for循环难以确定元素,我们可以使用while循环来遍历并修改元素!
student = ["li hong", "xiao ming", "da zhuang"] # 学生姓名
new_class = [] # 新的班级
while student: # 循环(若学生列表有元素)
temp_name = student.pop() # 不断弹出
new_class.append(temp_name) # 添加到新的班级列表中
print(student)
print(new_class)
输出:
[]
['da zhuang', 'xiao ming', 'li hong']
student = ["xiao ming", "li hong", "xiao ming", "da zhuang", "xiao ming"] # 有重复
while "xiao ming" in student: # 若 xiao ming 在学习列表中
student.remove("xiao ming") # 删除
print(student)
输出:
['li hong', 'da zhuang']
函数是带名字的代码块,用于完成具体的任务。要执行函数定义的任务,只需要调用该函数就行!
我们以下面的程序为例,关键词def 用来定义函数,其后面紧greet_user是函数名, 圆括号()中执行函数所需的信息,这里不需要额外信息。 greet_user() 是函数的调用,最终直接返回函数结果
def greet_user(): # def 函数名(形参):
"""显示问候语""" # 注释,写函数功能等
print("hello!!!")
greet_user()
输出:
hello!!!
def 函数名(参数):
函数体
name就是我们想函数中传递的参数!
def greet_user(name):
"""显示问候语"""
print("hello ", name)
greet_user("li ming")
上面代码中,变量name是函数中的形参, 即函数完成任务所需的信息;“li ming” 是一个 实参,即调用函数时,传递给函数的信息。
实际执行时,函数greet_user会将实参“li ming”赋值给形参name,然后完成函数!
函数中所需的形参有时很多,我们在调用函数时,需要传递多个实参给函数:
我们举例看看:
def student(name, age):
print("学生姓名: ", name)
print("学生年龄: ", age)
student("li ming", 18)
输出:
学生姓名: li ming
学生年龄: 18
上面函数有两个形参,所有我们调用函数时,需要传递两个实参,根据位置顺序,实参"li ming"传递给形参name,实参18传递给形参age;位置不能错!!!
函数也可以多次调用!如下面所示:
def student(name, age):
print("学生姓名: ", name)
print("学生年龄: ", age)
student("li ming", 18)
student("da zhuang", 20)
输出:
学生姓名: li ming
学生年龄: 18
学生姓名: da zhuang
学生年龄: 20
关键字实参是将参数名和值关联起来,这样可以不受顺序的影响,举例看看就懂:
def student(name, age):
print("学生姓名: ", name)
print("学生年龄: ", age)
student(name = "li ming", age = 18) # 调用时,直接赋值,student(age = 18, name = "li ming") 返回的结果一样!
输出:
学生姓名: li ming
学生年龄: 18
在函数编写时,可以给形参传递默认值,在调用函数时,若给这个形参传递了值,则用该值,若没有赋值,则函数会使用默认值!举例看看:
def student(name, age = 15):
print("学生姓名: ", name)
print("学生年龄: ", age)
student(name = "li ming")
输出:
学生姓名: li ming
学生年龄: 15
上述代码:形参age的默认值是15, 函数调用时没有给形参赋值实参,所以按默认值!
def student(name, age = 15):
print("学生姓名: ", name)
print("学生年龄: ", age)
student(name = "li ming", age = 18)
输出:
学生姓名: li ming
学生年龄: 18
上述代码:函数调用时,给所以形参都传递了实参,所以不会按照默认值!
函数并不是像上面直接显示值,还可以处理数据后,返回一个值或一组值,函数返回的值称为返回值。我们可以用 return语句 将函数处理结果返回出来!
def student(first_name, last_name):
name = f"{first_name} {last_name}"
return name # 返回函数最终结果(name变量)
result_name = student('li', 'ming') # 将函数返回值 name 赋值给 变量 result_name
print(result_name)
输出:
li ming
根据上面的代码,有时名字有三个字,我们需要加上一个形参,但名字还有两个字的,所以第三个形参就是可选的,我们可以给它一个默认值!防止报错,并将其放在形参列表的末尾!,放中间会报错!
def student(first_name, last_name, middle_name = ""):
if middle_name:
name = f"{first_name} {middle_name} {last_name}"
else:
name = f"{first_name} {last_name}"
return name
result_name = student('li', 'ming')
print(result_name)
result_name = student("xiao", 'ke', 'ai')
print(result_name)
输出:
li ming
xiao ai ke
函数不仅可以一个值,也可以返回一组值,如列表、字典等等!
def student(first_name, last_name, age = None): # age是可选形参
person = {
"first": first_name, "last": last_name}
if age:
person['age'] = age
return person
result = student('li', 'ming', 17)
print(result)
输出:
{
'first': 'li', 'last': 'ming', 'age': 17}
有时我们很多信息存储在列表中,这时将信息传递给函数就很方便,我们来看看:
def student(names):
for name in names:
temp = f"hello {name}"
print(temp)
usernames = ['li ming', 'xiao hong', 'da zhuang']
student(usernames)
输出:
hello li ming
hello xiao hong
hello da zhuang
有时,我们不知道函数需要多少个实参,而python可以从调用的函数中取任意数量的实参,具体看看:
def student(*names):
print(names)
student("li ming") # 传递一个实参和三个实参,可以的
student('li ming', 'xiao hong', 'da zhuang')
输出:
('li ming',)
('li ming', 'xiao hong', 'da zhuang')
上述代码中, 形参names前面的 * 会创建一个名为names的空元组,并接受任意传进来的实参封装到元组中。然后传递给函数!
注意:
若要让函数接受不同类型的实参,必须在函数定义中将接受任意数量实参的形参放在最后。python先匹配位置参数和关键字参数,再将余下的实参都收集到最后一个形参中!
def student(age, *names):
print(age, names)
student(18, "li ming") # 将18传给age,剩下的实参传递给names
student(16, 'li ming', 'xiao hong', 'da zhuang') # 将16传给age,剩下的所有实参传递给names
输出:
18 ('li ming',)
16 ('li ming', 'xiao hong', 'da zhuang')
有时,需要接受任意数量的实参,但不知道传递给函数的是什么信息。这时我们可以将函数写为接受任意数量的键值对,调用函数时,传递多少实参就接受多少!举例看看
def student(first, last, **user_info):
user_info['first_name'] = first
user_info['last_name'] = last
return user_info
user = student('li', 'ming', age = 18, location = 'princeton')
print(user)
输出:
{
'age': 18, 'location': 'princeton', 'first_name': 'li', 'last_name': 'ming'}
上述代码中,形参**user_info 中的两个 **会创建一个名为user_info的空字典,并将接收函的所有键值对放入里面!
使用函数可以将 代码块 和 主程序 分离开,这样使得主程序显的清晰明了!我们将函数存储在称为模块的独立文件夹中,再将模块导入主程序中。 import 语句可以将模块导入到当前程序中!
我们首先创建模块。模块的扩展名是 .py文件 ,其中有我们提前写好的一个功能函数。我们举个例子看看:
我们写一个函数如下,文件命名为 print_name.py 。
def print_information(student):
print("student information: \n")
print(student)
在主程序中,用import语句导入模块(代码),然后
import print_name # print_name 是要导入的文件名
student = ['li hong', 'xiao ming', 'da zhuang'] # 定义列表
print_name.print_information(student) # 文件名.函数名 就可以调用函数了
输出:
student information:
['li hong', 'xiao ming', 'da zhuang']
上面我们通过 import语句 导入了整个模块,然后再调用其中具体的函数。我们也可以直接导入我们要使用的具体函数: from 模块文件名 import 函数名
若要导入多个函数可以使用逗号隔开:from 模块文件名 import 函数名,函数名,函数名
所有上面的例子,我们可以直接导入要使用的函数:
from print_name import print_information # 直接导入我们要的函数
student = ['li hong', 'xiao ming', 'da zhuang']
print_information(student)
输出:
student information:
['li hong', 'xiao ming', 'da zhuang']
有时导入的函数名和主程序的名称重复,或本身名称过长,这时我们就可以使用as关键词改名!
from print_name import print_information as pi # 使用as改名为pi
student = ['li hong', 'xiao ming', 'da zhuang']
pi(student)
也可以直接对模块改名!
import print_name as pn # 直接改名模块的名称!
student = ['li hong', 'xiao ming', 'da zhuang']
pn.print_information(student)
使用 * 来导入模块中的所有函数!
from print_name import * # 导入模块中的所有函数!
student = ['li hong', 'xiao ming', 'da zhuang']
print_information(student) # 直接调用就行!
面向对象编程是最有效的软件编写方法之一,在面向对象编程中,我们可以构建一个表现任何事物或情境的类,并根据类创建对象。编写类时,我们所定义的类具有所有对象的通用行为!
基于类创建的对象,都自动具有类的通用行为,然后根据需要赋予每个对象独立的特征,来完成具体任务!
根据类来创建对象称为实例化 , 这样就可以使用类的实例!
使用类几乎可以模拟任何东西,我们编写一个小狗的类Dog,这个类不是指特定的小狗,而是任何小狗。 对于小狗来说,它们有名字、年龄,它们还会蹲下、打滚。由于小狗具有上述两个信息(名字、年龄)和两种行为(蹲下、打滚),所有我们的类Dog将包含这些信息!
具体如下:
class Dog: # 定义一个名为Dog的类
"""对小狗的简单模拟""" # 对类的功能做说明
def __init__(self, name, age): # 初始化方法
"""初始化属性name和age"""
self.name = name # 定义属性name
self.age = age # 定义属性age
def sit(self): # 定义方法(蹲下)
"""模拟小狗收到命令时蹲下!"""
print(f"{self.name} is now sitting.")
def roll_over(self): # 定义方法(打滚)
"""模拟小狗收到命令时打滚"""
print(f"{self.name} rolled over")
方法 __ init __() :
self.name = name 解释说明:
Dog类还定义了另外两个方法,sit() 和 roll_over() ,这些方法执行时不需要额外的信息,因此只有一个形参self。之后创建的实例都能够访问这些方法,即小狗都会下蹲和打滚。当前的两个方法只是打印出来具体的状态,我们也可以对这块复杂化,加一个具体的行动等等!
我们创建一个具体的小狗:
# Dog类的创建代码在上面
my_dog = Dog("xiao hei", 3)
print(my_dog.name)
print(my_dog.age)
输出:
xiao hei
3
my_dog = Dog(“xiao hei”, 3) :
创建了一条名为“xiao hei”、年龄是3的小狗。执行这行代码后,python使用实参“xiao hei”和“3”来调用Dog类的方法 __ init () 。方法 init __()创建一个特定小狗的实例,并将实参传递给形参name和age,之后python返回一个表示这个小狗的实例,而我们将实例赋值给变量 my_dog!
my_dog = Dog("xiao hei", 3)
my_dog.sit()
my_dog.roll_over()
输出:
xiao hei is now sitting.
xiao hei rolled over
my_dog = Dog("xiao hei", 3) # 创建实例 my_dog
your_dog = Dog("da zhuang", 5) # 创建实例 your_dog
print(my_dog.name) # 实例 my_dog 的属性
print(my_dog.age) # 实例 my_dog 的属性
print(your_dog.name) # 实例 your_dog 的属性
print(your_dog.age) # 实例 your_dog 的属性
my_dog.sit() # 实例 my_dog的方法
my_dog.roll_over() # 实例 my_dog的方法
your_dog.sit() # 实例 your_dog 的方法
your_dog.roll_over() # 实例 your_dog 的方法
输出:
xiao hei
3
da zhuang
5
xiao hei is now sitting.
xiao hei rolled over
da zhuang is now sitting.
da zhuang rolled over
上面,我们定义了两个实例,每个实例都有自己特定的属性,并能够执行相同的方法!
可以使用类来描述现实世界的很多事物和情景。类编写好后,我们可以创建很多的实例,我们常常会依据任务来修改实例的属性、方法等等!
编写一个表示汽车的类:
class Car:
"""模拟汽车"""
def __init__(self, make, model, year):
"""初始化描述汽车的属性"""
self.make = make # 制造商
self.model = model # 型号
self.year = year # 生产年份
def get_descriptive_name(self):
"""返回清晰的信息"""
lone_name = f"{self.year} {self.make} {self.model}" # 汽车整体信息
return lone_name.title() # 首字母大写
my_new_car = Car("audi", 'a4', '2019') # 创建实例,赋值给 my_new_car
print(my_new_car.get_descriptive_name()) # 调用类中的方法 get_descriptive_name
输出:
2019 Aodi A4
上述代码中,我们创建了一个Car类,给了其三个属性(make、model、year)和一个方法(get_descriptive_name),下面我们对它继续修改
创建实例时,有些属性无需通过形参定义,可在方法 __ init __() 中为其指定默认值 。
下面添加一个名为 odometer_reading 的属性,其初始值为0,。我们还添加一个名为read_odometer()的方法,用于读取汽车的里程表:
class Car:
"""模拟汽车"""
def __init__(self, make, model, year):
"""初始化描述汽车的属性"""
self.make = make # 制造商
self.model = model # 型号
self.year = year # 生产年份
self.odometer_reading = 0 # 里程数 默认为0
def get_descriptive_name(self):
"""返回清晰的信息"""
lone_name = f"{self.year} {self.make} {self.model}"
return lone_name.title()
def read_odometer(self):
"""打印一条汽车公里数的消息"""
print(f"This car has {self.odometer_reading} miles on it.")
my_new_car = Car("audi", 'a4', '2019') # 创建实例,赋值给 my_new_car
print(my_new_car.get_descriptive_name()) # 调用类中的方法 get_descriptive_name
my_new_car.read_odometer() # 调用类中的方法 read_odometer
输出:
2019 Audi A4
This car has 0 miles on it.
上述代码中,我们给属性 odometer_reading 了一个默认值 0 !即汽车出厂的公里数为0,这一般是不合理的,所以需要对该属性的值进行修改
一般有三种修改的方法:
# Car类 代码和上面相同
my_new_car = Car("audi", 'a4', '2019') # 创建实例,赋值给 my_new_car
print(my_new_car.get_descriptive_name()) # 调用类中的方法 get_descriptive_name
my_new_car.odometer_reading = 23 # 直接对属性修改
my_new_car.read_odometer() # 调用方法
输出:
2019 Audi A4
This car has 23 miles on it.
class Car:
"""模拟汽车"""
"""中间同上"""
def updata_odometer(self, mileage): # 通过方法直接对属性进行修改!
"""将里程数设置为指定值"""
self.odometer_reading = mileage
my_new_car = Car("audi", 'a4', '2019') # 创建实例,赋值给 my_new_car
print(my_new_car.get_descriptive_name()) # 调用类中的方法 get_descriptive_name
my_new_car.updata_odometer(23) # 调用方法来直接修改属性值
my_new_car.read_odometer()
输出:
2019 Audi A4
This car has 23 miles on it.
class Car:
"""模拟汽车"""
"""中间同上"""
def updata_odometer(self, mileage):
"""将里程数设置为指定值"""
self.odometer_reading = mileage
def increase_odometer(self, miles):
"""将里程数增加一定量"""
self.odometer_reading += miles
my_new_car = Car("audi", 'a4', '2019') # 创建实例,赋值给 my_new_car
print(my_new_car.get_descriptive_name()) # 调用类中的方法 get_descriptive_name
my_new_car.updata_odometer(2300) # 修改属性(指定里程数)
my_new_car.read_odometer()
my_new_car.increase_odometer(100) # 修改属性(增加里程数)
my_new_car.read_odometer()
输出:
2019 Audi A4
This car has 2300 miles on it.
This car has 2400 miles on it.
通过上面三种方式:
编写类时,并不是从空白开始,如果我们编写的 类B 是从 类A 改变过来的,可使用继承!类B继承类A时,将自动获得类A的所有属性和方法。这时类A叫做父类,而类B叫做子类。
子类继承了父类的所有属性和方法,同时还可以定义自己的属性和方法 !
在现有类的基础上建立新类时,一般要调用父类的方法 __ init __(),这将初始化在父类 __ init __() 方法中定义的所有属性,从而让子类包含这些属性!
上面我们建立了Car类,模拟了汽车,若我们要模拟电动汽车呢?电动汽车具备一般汽车的属性,还有自己的独有属性和方法!
# 定义父类 Car
class Car:
"""模拟汽车"""
def __init__(self, make, model, year):
"""初始化描述汽车的属性"""
self.make = make # 制造商
self.model = model # 型号
self.year = year # 生产年份
self.odometer_reading = 0 # 里程数 默认为0
def get_descriptive_name(self):
"""返回清晰的信息"""
lone_name = f"{self.year} {self.make} {self.model}"
return lone_name.title()
def read_odometer(self):
"""打印一条汽车公里数的消息"""
print(f"This car has {self.odometer_reading} miles on it.")
def updata_odometer(self, mileage):
"""将里程数设置为指定值"""
self.odometer_reading = mileage
def increase_odometer(self, miles):
"""将里程数增加一定量"""
self.odometer_reading += miles
# 定义子类 ElectricCar
class ElectricCar(Car):
"""电动汽车"""
def __init__(self, make, model, year):
"""初始化父类的属性"""
super().__init__(make, model, year) # 让子类包含父类的所有属性
my_tesla = ElectricCar("tesla", 'model s', '2019') # 创建实例
print(my_tesla.get_descriptive_name()) # 调用父类中的方法
输出:
2019 Tesla Model S
接下来,我们可以赋予电动车一些自己独特的属性和方法
class Car:
"""模拟汽车"""
"""中间同上"""
class ElectricCar(Car):
"""电动汽车的独特之处"""
def __init__(self, make, model, year):
super().__init__(make, model, year) # 初始化父类的属性
self.battery_size = 75 # 初始化电动汽车独有的属性
def describe_battery(self):
"""打印一条描述电池容量的消息"""
print(f"This car has a {self.battery_size} -kwh battery.")
my_tesla = ElectricCar("tesla", 'model s', 2019) # 创建实例,赋值给 my_new_car
print(my_tesla.get_descriptive_name()) # 调用类中的方法 get_descriptive_name
my_tesla.describe_battery()
输出:
2019 Tesla Model S
This car has a 75 -kwh battery.
上面代码中,根据类ElectricCar创建的所有实例都将包含属性 battery_size , 而父类Car的所有实例都不会包含这个属性。
对子类ElectricCar的特殊程度没有任何限制(可以加入电动车自身独有的任何属性和方法)。但当某个属性或方法是任何汽车都有的,并不是电动车独有的,这时应该将其加入Car类 而不是类ElectricCar中。
若父类中的方法不符合子类中的要求,比如Car类中有油箱,但是ElectricCar类中是没有的,这时我们可以定义一个和该方法同名的方法。这样,python就会优先考虑子类中的方法!
例如Car类中有一个名为 fill_gas_tank()的方法,电动车是没有油箱的!因此我们可以重写该方法:
class Car:
"""模拟汽车"""
"""中间同上"""
class ElectricCar(Car):
"""电动汽车的独特之处"""
def __init__(self, make, model, year):
super().__init__(make, model, year)
self.battery_size = 75
def describe_battery(self):
"""打印一条描述电池容量的消息"""
print(f"This car has a {self.battery_size} -kwh battery.")
def fill_gas_tank(self): # 直接对方法fill_gas_tank重写!
"""电动车没有油箱"""
print("This car doesn't need a gas tank.")
这时,若调用 类ElectricCar中的 fill_gas_tank()方法,python将忽略父类Car中的 fill_gas_tank()方法,而直接调用子类 fill_gas_tank()中的方法!
用代码模拟事物时,随着事物的复杂度,我们会添加很多的属性和方法,使得这个文件很长。这种情况下,可能需要将类的一部分提取出来,作为一个新类。
例如描述电动汽车ElectricCar,我们可能会将电池的情况描述的很详细,这时就可以让电池作为新的类Battery,并将一个实例Battery作为类ElectricCar类的属性!具体如下:
class Car:
"""模拟汽车"""
"""中间同上"""
class Battery:
"""对电池的模拟"""
def __init__(self, battery_size = 75):
"""初始化电池的大小"""
self.battery_size = battery_size
def describe_battery(self):
"""打印一条有关电瓶大小的消息"""
print(f"This car has a {self.battery_size} -kwh battery.")
class ElectricCar(Car):
"""电动汽车的独特之处"""
def __init__(self, make, model, year):
super().__init__(make, model, year) # 初始化父类的属性(Car类)
self.battery = Battery() # 初始化电动车的特有属性(battery类)
my_tesla = ElectricCar("tesla", 'model s', 2019) # 创建实例(电动汽车的示例)
print(my_tesla.get_descriptive_name()) # 调用父类中的方法
my_tesla.battery.describe_battery() # 实例my_tesla查找属性battery,然后对存储在属性中的Battery实例调用方法describe_battery()
上述代码中:
上面提到,我们可以拆分类来实现整体代码的阅读性,但由于描述的事物过于复杂,整体文件还是会很长,这里我们也可以像函数一样,先将类存储到模块中,再将其导入到主程序中!
我们创建一个 car.py 的文件(模块),来描述汽车!
"""一个用来表示汽车的类""" # 对该文档的说明描述(好的编程习惯,就应该加上具体的描述)
class Car:
"""模拟汽车"""
def __init__(self, make, model, year):
"""初始化描述汽车的属性"""
self.make = make # 制造商
self.model = model # 型号
self.year = year # 生产年份
self.odometer_reading = 0 # 里程数 默认为0
def get_descriptive_name(self):
"""返回清晰的信息"""
lone_name = f"{self.year} {self.make} {self.model}"
return lone_name.title()
def read_odometer(self):
"""打印一条汽车公里数的消息"""
print(f"This car has {self.odometer_reading} miles on it.")
def updata_odometer(self, mileage):
"""将里程数设置为指定值"""
self.odometer_reading = mileage
def increase_odometer(self, miles):
"""将里程数增加一定量"""
self.odometer_reading += miles
然后创建另一个文件 my_car.py,并在其中导入Car类并创建具体实例:
from car import Car # 打开文件(模块)car 导入其中的 Car 类
my_new_car = Car("audi", "a8", "2020") # 初始化实例
print(my_new_car.get_descriptive_name()) # 调用方法
my_new_car.odometer_reading = 52 # 属性赋值
my_new_car.read_odometer() # 调用方法
输出:
2020 Audi A8
This car has 52 miles on it.
同一个模块中的类有一定的相关性,但也可以根据需要在一个模块中存储任意数量的类。我们在上面Car类的基础上再加 Battery类和ElectricCar类 !
"""一组用于表示燃油车和电瓶汽车的类""" # 对文件(模块)的描述
class Car:
"""模拟汽车"""
def __init__(self, make, model, year):
"""初始化描述汽车的属性"""
self.make = make # 制造商
self.model = model # 型号
self.year = year # 生产年份
self.odometer_reading = 0 # 里程数 默认为0
def get_descriptive_name(self):
"""返回清晰的信息"""
lone_name = f"{self.year} {self.make} {self.model}"
return lone_name.title()
def read_odometer(self):
"""打印一条汽车公里数的消息"""
print(f"This car has {self.odometer_reading} miles on it.")
def updata_odometer(self, mileage):
"""将里程数设置为指定值"""
self.odometer_reading = mileage
def increase_odometer(self, miles):
"""将里程数增加一定量"""
self.odometer_reading += miles
class Battery:
"""对电池的模拟"""
def __init__(self, battery_size = 75):
"""初始化电池的大小"""
self.battery_size = battery_size
def describe_battery(self):
"""打印一条有关电瓶大小的消息"""
print(f"This car has a {self.battery_size} -kwh battery.")
def get_range(self):
"""打印一条描述电瓶容量的消息"""
if self.battery_size == 75:
range = 260
elif self.battery_size == 100:
range = 315
print(f"This car can go about {range} miles on a full charge.")
class ElectricCar(Car):
"""电动汽车的独特之处"""
def __init__(self, make, model, year):
super().__init__(make, model, year) # 初始化父类的属性
self.battery = Battery() # 初始化电动车的特有属性
现在创建一个名为 my_electric_car.py 的文件,将上面的导入:
from car import ElectricCar # 打开文件(模块)导入 类ElectricCar
my_tesla = ElectricCar("tesla", "model s", 2020) # 创建实例
print(my_tesla.get_descriptive_name()) # 调用方法
my_tesla.battery.describe_battery() # 调用方法
my_tesla.battery.get_range() # 调用方法
输出:
2020 Tesla Model S
This car has a 75 -kwh battery.
This car can go about 260 miles on a full charge.
可以在主程序中导入任意数量的类,比如我们要创建一个普通汽车和电动汽车,那么我们就要导入Car类和ElectricCar类:
from car import Car, ElectricCar # 从文件(模块)导入类Car、类ElectricCar
my_beetle = Car("volkswagen", "beetle", 2020) # 创建实例
print(my_beetle.get_descriptive_name()) # 调用方法
my_tesla = ElectricCar("tesla", "model s", 2020) # 创建实例
print(my_tesla.get_descriptive_name()) # 调用方法
输出:
2020 Volkswagen Beetle
2020 Tesla Model S
上面我们导入模块中的一个类、多个类,当然也可以导入整体模块,然后根据句点法调用具体的类!
import car # 导入整个模块
my_beetle = car.Car("volkswagen", "beetle", 2020) # 创建实例(调用具体类)
print(my_beetle.get_descriptive_name())
my_tesla = car.ElectricCar("tesla", "model s", 2020) # 创建实例(调用具体类)
print(my_tesla.get_descriptive_name())
输出:
2020 Volkswagen Beetle
2020 Tesla Model S
要导入模块(文件)中的所有类,可以用:
from model_name import * # 这样导入了模块(文件)中的所有类
这种做法的有一些缺点:
我们可以用9.4.4中的做法,导入模块后,用句点法来使用具体的类!
有时,我们会把类存储在多个模块中,以免模块太多!将类存储在多个模块中,有时一个模块中的类可能会依赖其他模块中的类,这时可在前一个模块中导入必要的类!举例说明:
我们将Car类存储在一个模块car.py中,ElectricCar类、Battery类存储在另一个模块electric_car.py中:
模块 car.py:
"""用于表示汽车的类""" # 对文件(模块)的描述
class Car:
"""模拟汽车"""
def __init__(self, make, model, year):
"""初始化描述汽车的属性"""
self.make = make # 制造商
self.model = model # 型号
self.year = year # 生产年份
self.odometer_reading = 0 # 里程数 默认为0
def get_descriptive_name(self):
"""返回清晰的信息"""
lone_name = f"{self.year} {self.make} {self.model}"
return lone_name.title()
def read_odometer(self):
"""打印一条汽车公里数的消息"""
print(f"This car has {self.odometer_reading} miles on it.")
def updata_odometer(self, mileage):
"""将里程数设置为指定值"""
self.odometer_reading = mileage
def increase_odometer(self, miles):
"""将里程数增加一定量"""
self.odometer_reading += miles
模块 electric_car.py:
"""用于表示电动汽车和电池的类""" # 对文件(模块)的描述
from car import Car # 先将类Car 导入
class Battery:
"""对电池的模拟"""
def __init__(self, battery_size = 75):
"""初始化电池的大小"""
self.battery_size = battery_size
def describe_battery(self):
"""打印一条有关电瓶大小的消息"""
print(f"This car has a {self.battery_size} -kwh battery.")
def get_range(self):
"""打印一条描述电瓶容量的消息"""
if self.battery_size == 75:
range = 260
elif self.battery_size == 100:
range = 315
print(f"This car can go about {range} miles on a full charge.")
class ElectricCar(Car):
"""电动汽车的独特之处"""
def __init__(self, make, model, year):
super().__init__(make, model, year) # 初始化父类的属性
self.battery = Battery() # 初始化电动车的特有属性
主程序 my_cars.py:
from car import Car
from electric_car import ElectricCar
my_beetle = Car("volkswagen", "beetle", 2020)
print(my_beetle.get_descriptive_name())
my_tesla = ElectricCar("tesla", "model s", 2020)
print(my_tesla.get_descriptive_name())
输出:
2020 Volkswagen Beetle
2020 Tesla Model S
上一章中,函数导入时可以将函数名改为其他名称,对于类也是可以的!举例如下:
from electric_car import ElectricCar as EC # 将类ElectricCar 改为 EC
若要创建电动车实例时,只需要调用 EC就行
my_tesla = EC("tesla", "model s", 2020)
python标准库是一组模块,我们安装好python后就包含它了。我们对函数和类的模块原理已经了解了,同理也使用其他人编写好的模块,我们只需要: import 模块名
以 random模块 为例,它其中有一个函数为 randint()
from random import randint # 导入模块
result = randint(1, 10) # 传入两个整数,返回其范围中任意数字
print(result)
输出:
4
模块random中,另外一个函数choice()。它将一个列表或元组作为参数,返回其中随机一个元素:
from random import choice
result = choice(["li ming", "xiao hong", "da zhuang"])
print(result)
输出:
xiao hong
本章学习python对文件的处理、对程序运行错误的处理以及json模块,用来保存数据防止程序停止运行后丢失!
日常中,文本文件最多,我们应该学会如何去处理这些文件,在使用或处理这文本时,我们应先读取这些文件,可以一次性全部读取,也可以逐行的读取!
首先我们创建一个文本文件 pi_digits.txt ,其内容为:
3.1415926535
8979323846
2643383279
我们一次性读取文本中所有内容
with open("pi_digits.txt") as file_object: # 打开文件
contents = file_object.read() # 读取文件所有内容
print(contents)
输出:
3.1415926535
8979323846
2643383279
我们解读一下上面的代码:
上面代码中,open()函数中传递的文件目录是相对路径,即该文件所在目录相对于当前程序运行所在的目录!有时为了防止出错,可以使用绝对路径,即文件在计算机中的位置!
有时我们需要对文件中的内容进行逐行的读取,用于修改或查看等等!我们继续用上面的例子来说;
filename = "pi_digits.txt" # 文件的路径
with open(filename) as file_object: # 打开文件
for line in file_object: # 逐行读取(通过循环)
print(line) # 打印
输出:
3.1415926535
8979323846
2643383279
上述打印出来的有很多的空行,和文件中的不一样,因为文件中每行的末尾都有一个换行符,而print()在读取时也会加上一个换行符,这时就有两个换行符:一个来自文件,一个来自print()函数,我们可以使用rstrip()函数来消除:
filename = "pi_digits.txt"
with open(filename) as file_object:
for line in file_object:
print(line.rstrip())
输出:
3.1415926535
8979323846
2643383279
使用关键词with时,open()返回的文件对象只能在with代码块中使用。若要在with代码块外面访问文件内容,可以在with代码块中将文件各行存储在一个列表中,然后在with代码块外面使用!
filename = "pi_digits.txt" # 文件目录
with open(filename) as file_object: # 打开文件
lines = file_object.readlines() # 读取文件,存放到列表中
print(lines)
for line in lines: # 通过循环打印出文件信息
print(line.rstrip())
输出:
['3.1415926535\n', '8979323846\n', '2643383279'] # 整个文件存储在列表中,每行作为列值中一个元素
3.1415926535
8979323846
2643383279
当我们想要保存某些数据时,通常的做法就是直接对其保存,将数据写到一个文件中!举例看看:
filename = "programming.txt" # 文件目录
with open(filename, "w") as file_object: # 打开文件,写入模式
file_object.write("I love programming") # 写入数据(此处是一个字符串)
# programming.txt 文件中的内容
I love programming
解释上述代码:
函数 write()不会在写入的文件末尾添加换行符,若要写入多行文件时,可能达不到预期想要的!举例看看:
filename = "programming.txt"
with open(filename, "w") as file_object:
file_object.write("I love programming.")
file_object.write("I love creating new games.")
查看文件,发现上面写入的两句话变成一行了!
# programming.txt 文件中的内容
I love programming.I love creating new games.
要让每个字符串占一行,就应该在字符串后面加换行符!
filename = "programming.txt"
with open(filename, "w") as file_object:
file_object.write("I love programming.\n") # 字符串后面加换行符
file_object.write("I love creating new games.\n")
# programming.txt 文件中的内容
I love programming.
I love creating new games.
上面提到,在 写入模式(“w”) 中,若文件已经存在,python会将文件中的内容删除,再写入数据。那若要在原有文件继续写入数据呢?这时就要使用附加模式(“s”),当然文件若不存在,python也是会提前创建一个空文件的!
我们对上面的文件 programming.txt 继续修改,给它添加一些信息:
filename = "programming.txt"
with open(filename, "a") as file_object:
file_object.write("I also love finding meaning in large datasets.\n")
file_object.write("I love creating apps that can run in a browser.")
# programming.txt 文件中的内容
I love programming.
I love creating new games.
I also love finding meaning in large datasets.
I love creating apps that can run in a browser.
我们发现,原本的文件信息还在,下面两行是刚添加上的!
程序发生错误后,会停止运行并报错;但是有时我们不知道程序还有什么问题,为了提前避免程序发生错误停止运行,python中有称为异常的一个对象可以管理程序发生错误!当程序发生错误后,会走我们提前指定的路线执行!
异常吹模块: try - except
我们知道除法中,除数不能为零,程序碰到这种情况会报错,我们看看:
print(5/0)
输出:
Traceback (most recent call last):
File "C:/Users/Administrator/PycharmProjects/venv/my_cars.py", line 1, in <module>
print(5/0)
ZeroDivisionError: division by zero
python一旦遇到错误就会停止执行!
一般就代码块放在try语句下,若代码块报错,将执行except下的代码,若代码块没有报错,就忽略except下的代码!
try:
print(5/0) # 代码在try中,报错则执行except;否则忽略except
except ZeroDivisionError:
print("You can't divide by zero")
由于知道try中程序可能报ZeroDivisionError错误,若不知道将会报什么错,也可以不写,如下:
try:
print(5/0)
except: # 直接写except
print("You can't divide by zero")
有时程序在执行过程中,为了防止报错而导致后续程无法执行,就应该加上try-except:
print("这是一个简单的除法计算器")
while True:
first_number = input("请输入第一个数: ")
second_number = input("请输入第二个数: ")
answer = float(first_number) / float(second_number)
print(answer)
输出:
这是一个简单的除法计算器
请输入第一个数: 5
请输入第二个数: 0
Traceback (most recent call last):
File "F:/py_object/alien_invasion/1.py", line 6, in <module>
answer = float(first_number) / float(second_number)
ZeroDivisionError: float division by zero
上述代码中,当除数为零时就会报错,导致程序后续无法执行,这时就应该用异常处理模块!
在python中,若将代码块放在try中,若程序报错,就执行except中的代码,若执行成功,我们可以在else中进行打印或执行:
print("这是一个简单的除法计算器")
while True:
first_number = input("请输入第一个数: ")
second_number = input("请输入第二个数: ")
try:
answer = float(first_number) / float(second_number)
except ZeroDivisionError:
print("除数不应该为零")
else:
print(answer)
输出:
这是一个简单的除法计算器
请输入第一个数: 5
请输入第二个数: 0
除数不应该为零
处理文件数据时,若程序找不到文件一般会报错,
filename = "ceshi.txt"
try:
with open(filename, encoding='UTF-8') as file: # 打开文件
lines = file.read()
except FileNotFoundError: # 报错
print(f"Sorry, The file {filename} does not exist")
输出:
Sorry, The file ceshi.txt does not exist
我们还会遇到很多的错误,基本都可以使用这样的方式去处理!
前面程序中,程序遇到错误后,都会去执行excep中的程序,我们都会打印一个报错的信息,但有时我们想一直去执行,不需要打印什么报错信息,这时就可以使用 pass
filename = "ceshi.txt"
try:
with open(filename, encoding='UTF-8') as file: # 打开文件
lines = file.read()
except FileNotFoundError: # 若出错,什么都不打印!
pass
输出:
我们经常需要把程序中的一些数据如:列表、字典等数据保存在文件中!一种简单的方式是使用 json模块 存储数据!
JSON数据格式并非python专用,可以和其他编程语言一起共享数据!
我们举例看看:
# 写文件
import json # 导入json模块
numbers = [1, 2, 3, 4, 5] # 要存储的列表
filename = "numbers.json" # 文件
with open(filename, 'w') as file: # 打开文件
json.dump(numbers, file) # 写入列表到文件中
# 读取文件
import json
filename = "numbers.json" # 文件
with open(filename, 'r') as file: # 打开文件
numbers = json.load(file) # 加载文件
print(numbers)
输出:
[1, 2, 3, 4, 5]
我们写好的代码,都应该经过一系列的测试去看是否达到我们的预期!
我们先写一个简单的代码:
# 传入姓和名,打印出完整的姓名,首字母大写
def get_formatted_name(first, last):
"""生成完整的姓名"""
full_name = f"{first} {last}"
return full_name.title()
我们重新建立一个python脚本,将上面函数导入。并编写测试函数:
from name_function import get_formatted_name # 导入函数
print("Enter 'q' at any time to quit.\n")
while True:
first = input("Please give me a first name: ")
if first == "q":
break
last = input("Please give me a last name: ")
if last == "q":
break
formatted_name = get_formatted_name(first, last)
print(f"Neatly formatted name: {formatted_name}")
python中的 模块unittext 提供了代码测试工具。
单元测试:核实函数的某些方面没有问题
测试用例:是一组测试单元,用来核实函数在各种情形下的行为都符合要求!
我们使用python中的unittest模块!
import unittest # python标准库
from name_function import get_formatted_name # 被测试的函数
class NameTestCase(unittest.TestCase): # 要继承unittest.TestCase这个类
def test_first_last_name(self):
"""测试像姓和名为 'janis' 和 'joplin' 的用例"""
formatted_name = get_formatted_name('janis', 'joplin')
self.assertEqual(formatted_name, 'Janis Joplin') # assertEqual:断言方法,用来核实输出和期望是否一致
if __name__ == '__main__':
unittest.main()
输出:
============================= test session starts =============================
platform win32 -- Python 3.7.4, pytest-5.2.1, py-1.8.0, pluggy-0.13.0 -- D:\Anaconda\python.exe
cachedir: .pytest_cache
rootdir: F:\py_object\alien_invasion
plugins: arraydiff-0.3, doctestplus-0.4.0, openfiles-0.4.0, remotedata-0.3.2
collecting ... collected 1 item
test_name_function.py::NameTestCase::test_first_last_name PASSED [100%]
============================== 1 passed in 0.02s ==============================