Python程序设计(上)

Python语言是一种相对容易学习、功能强大的高级程序设计语言,它既支持面向过程的程序设计,同时也支持面向对象的编程,而且具有高效的数据结构。Python语言具有优雅地语法、动态类型以及解释类型的语言。
Python标识符(变量)的要求:
在Python中,标识符由字母、汉字、数字和下划线组成,但不能以数字开头,不能与关键字同名,标识符中使用的字母是区分大小写的。

  1. 基本数据类型
    Python的基本数据类型包括数值类型、字符串类型、布尔(bool)类型和空值(None)
    1.1 数值类型
    1.整型数据(int) 整型常量可以用十进制、八进制、二进制和十六进制
    十进制如: 123、-326、0
    二进制整数用0b或0B作为前缀,只有0和1两个数字,例如:0b1010
    八进制整数用0o或0O作为前缀,一共有八个数字,就是0~7 例如:0o367
    十六进制整数用0x或0X作为前缀,一共有16个数字,就是数字09和小写字母af或大写字母A~F,例如:0xcccc
    1.2浮点型数据
    浮点型数据(float) 就是带小数点的数据,浮点型数据有两种表达形式:十进制小数形式和指数形式.
    十进制小数形式由数字和小数点组成,例如:1.23、3.14159,此外,如果小数点后面也只有零,例如:1.0可以写成1.如果小数点前面也只有零,那么也可以省略 如:0.2可以写成.2

指数形式用科学计数法表示浮点数,用字母e或E表示10为底数的指数,字母e前面为数字部分,可以带有小数,字母e后面为指数部分,必须为整数,数字部分和指数部分必须同时出现。
1.总结一下:数字部分和指数部分必须同时出现,指数部分,必须为整数 例如:3.6e3 、 2.39e-9 错误的有:1.2e1.5 e5 1.2e
1.3复数型数据
复数型数据(complex),复数是python内置的数据类型。复数的表示形式为a+bj,其中a为实数,b为虚数,j表示虚数单位,字母j也可以写成大写形式J.
在python语言中,可以使用real和imag属性来获取一个复数的实数部分和虚数部分.

2 字符串类型
字符串使用单引号、双引号(2个单引号或2个双引号)或三引号(3个单引号或3个双引号)括起来的任意文本
单行字符串 ‘hello’、“hello”
多行字符串
a = “”"
hello world
hello python
“”"
b = ‘’’
hello world
hello python
‘’’
字符串是不可变对象,字符串中的字符不能改变,每当修改字符串时系统都将生成一个新的字符串对象.
2.1 转义字符

  1. \0 空字符 2. \ 反斜杠
    3.’ 单引号’ 4. " 双引号 "
    5.\n 换行符 6. \t 水平制表符
    7.\r 按Enter键(回车键)

注意:\t水平制表符,是按照四个字符一个单位的,所有上面的print(“hello\tworld”)中间空三格
去转义字符 在字符串的前面加r/R,如:
print(r"hello\tworld")
3 运算符
按照功能可分为:算术运算符、赋值运算符(=)、关系运算符、逻辑运算符、位运算符、身份运算符、成员运算符。
按照操作数的数目可分为单目运算符、双目运算符、三目运算符
3.1算术运算符
算术运算符: + - * / % // **
算术运算符优先级 ** > * / % // > + -
如果有括号(),则括号的优先级大于**
例如: (1+2)**3+(1-2)*3 优先计算括号里面的
3.2增强型赋值运算符
算术运算符都有与之对应的增强型赋值运算符

3.3关系运算符
关系运算符: > >= < <= != ==
关系运算符优先级一样的.
关系运算符的比较结果返回的是bool类型的值

= < <= 不能将不同类型的数据进行比较,系统会报错(TypeError类型错误),而!= == 可以将不同类型的数据进行比较。
在比较字符串的时候,系统则会从左到右逐个比较每个字符的ASCII码,直到出现不同的字符为止。

3.4成员运算符
成员运算符 in not in 用于判断对象是否存在于字符串、列表等序列中,成员运算符优先级一样的。
print(1 in [1,2,3])
print(1 in [[1],2,3])
print([1] in [1,2,3])
print([1] in [[1],2,3])
print(1 not in [1,2,3])
print([1] not in [[1],2,3])
print(“ha” in “haha”)
print(“ha” not in “hhaa”)

3.5逻辑运算符
逻辑运算符: not and or
逻辑运算符的优先级: not > and > or
x and y 当x为True 返回y的值
x and y 当x为False 返回x的值
x or y 当x为True 返回x的值
x or y 当x为False 返回y的值
not x 当x为True 则表达式为False
当x为False 则表达式为True

逻辑运算符的简单应用:

3.6身份运算符
身份运算符: is is not
用于比较两个对象的内存地址是否相同
x = 1
y = 2
print(x is y)
x = 1
y = 1
print(x is y)
x = y = 1
print(x is not y)

3.7位运算符
位运算符用于对数字的二进制进行运算。位运算包括左移运算符(<<)、右移运算符(>>)、按位与运算符(&)、按位或运算符(|)、按位异或运算符(^)、按位取反运算符(~)

运算符 描述 示例
<< 左移运算符,将操作数的二进制位左位移若干位 2<<3返回16

右移运算符,将操作数的二进制位右位移若干位 20>>3返回2
& 按位与运算符,两个操作数相同时:都是1返回1,都是0返回0,操作数不同时,返回0 22&3返回2
| 按位或运算符,两个操作数都是0,返回0,其余返回1 32|3返回35
^ 按位异或运算符,两个操作数相同返回0,其余返回1 18^6返回20
~ 按位取反运算符,按照公式-x-1计算 ~32返回-33

ord() 能将字符或中文转为ASCII或Unicode码
chr() 能将ASCII或Unicode码转为字符或中文

4 流程控制结构
计算机程序主要由数据结构和算法结构两个要素组成,数据结构即数据的存储形式。算法则是对操作步骤的描述,即程序用什么方法对数据进行处理。
任何简单或复杂的算法都可以由顺序结构、选择结构和循环结构组合而成,通过这三种基本结构就可以实现程序的流程控制。
程序的工作流程一般为输入数据、处理数据、输出结果。
4.1赋值语句(=)
讲顺序结构之前来了解一下赋值语句
在python中,赋值语句分为简单赋值语句、复合赋值语句和多变量赋值语句。
1.简单赋值语句 用于对单个变量赋值

2.复合赋值语句

其中的x*=x+y,等价于: x=x*(x+y)
Python提供12中复合赋值运算符,包括算术运算的复合赋值运算符+=、-=、*=、/=、//=、%=、**=。位运算的复合赋值运算符:<<=、>>=、&=、|=、^=
3.多变量赋值语句

甚至可以将字典的键赋值给多个变量
其中的x=y=z=12叫链式赋值语句
x,y,z=12,13,14 叫同步赋值语句

4.2数据输入
标准输入 input([提示字符串])
num = int(input(“请输入正整数:”))
if num % 3 == 0 or num % 7 == 0:
print(“能被3或7整除”)
当需要输入多个数值的时候,可以使用eval()来同时输入,例如:
num1, num2, num3 = eval(input(“请输入num1,num2,num3用逗号隔开:”))
list1 = [num1, num2, num3]
list1.sort()
print(list1)

方法2:

num1, num2, num3 = input(“请输入num1,num2,num3用逗号隔开:”).split(“,”)
list1 = [int(num1), int(num2), int(num3)]
list1.sort()
print(list1)
4.3数据输出
数据输出可以通过两种方式来实现:第一种就是在交互模式下使用表达式语句来输出表达式的值,但是这种方式不能在脚本模式下使用,另一种方式是使用内置函数print(),这种方式在交互模式和脚本模式下均可使用。
name = “张三”

带一个变量输出

print("my name is ", name)

不带变量输出

print(“my name is 张三”)

带多个变量输出

age = 18
print(“my name is”, name, “my age is”, age)

不换行输出 end用于指定结束符(以指定的字符结尾)

print(“hello”,end=" ")
print(“world”)

sep 用于指定各输出项之间的分隔符(以指定的字符来分隔)

print(“my name is”, name, “my age is”, age,sep=“&”)

使用format输出变量,在输出项里面用{}来代替输出的变量

print(“my name is {} my age is {}”.format(name, age))
也可以指定变量输出,只需要在{}里面指定索引即可.
print(“my name is {1} my age is {1}”.format(name, age))

可以在字符串的前面加f,然后在{}里面直接放对应的变量

print(f"my name is {name} my age is {age}")

4.4格式化输出
%% 输出百分号,例如:
a=18
print(“我们国家人口增长%%%d”%a)
%d 输出十进制整数
height=185
print(“我的身高%dcm”%height)
%c输出ASCII码对应的字符
b = 97
print(“字母%c”%b)
%s输出字符串
name=“张三”
print(“my name is %s”%name)
%f 输出浮点型数据
height = 185.87
print(“my height is %.2f”%height) # .2表示的是将浮点型数据保留小数点后2位
print(“my height is %.1f”%height) # .1表示的是将浮点型数据保留小数点后1位,注意四舍五入
4.5顺序结构
顺序结构:就是程序自上而下执行,没有任何分支的结构。
a=1
b=2
print(a+b)
4.6选择结构
选择结构:选择结构是指程序运行时,系统根据某个特定的条件选择一个分支执行。
根据分支的多少,选择结构分为单分支选择结构、双分支选择结构、多分支选择结构。
根据实际需求,还可以在一个选择结构中嵌入另外一个选择结构
4.6.1单分支选择结构
语法结构:
if 表达式:
语句块
其中表达式表示条件,其值为布尔值。语句块必须向右缩进,如果包含多个语句块,这些语句块必须具有相同的缩进量。
如果语句块只有一个语句,则语句块可以和if 语句写在同一行。
例如: if i % 2 == 0: print(“偶数”)
例1:
从键盘输入一个年份,判断这一年是不是闰年。
闰年满足以下条件之一:1.能被4整除但不能100整除 2.能被400整除。
leapyear = “不是”
year = int(input(“请输入一个年份:”))
if (year % 4 == 0 and year % 100 != 0) or year % 400 == 0:
leapyear = “是”
print(“{}年{}闰年”.format(year, leapyear))
4.6.2双分支选择结构
双分支选择结构用于处理两个分支的情况,可以用if-else语句来实现,语法如下:
if 表达式:
语句块 1
else:
语句块 2
执行流程(N-S图):
if 表达式如果为True,执行语句块1,否则执行语句块2

例1:
从键盘输入三角形的3条边长,计算三角形的面积(结果保留两位)。
解析:
构成三角形的充要条件:任意两边之和大于第三边。用a,b,c表示三角形的的边长,则a+b>c and b+c>a and c+a>b.首先判断能否构成三角形,若能,则可用海伦公式s=math.sqrt(p(p-a)(p-b)(p-c)) 其中的p=(a+b+c)/2来计算三角形的面积。
代码演示:
a, b, c = eval(input(“请输入三角形的三条边长:”))
if a + b > c and b + c > a and a + c > b:
p = (a + b + c) / 2
s = (p * (p - a) * (p - b) * (p - c)) ** 0.5
print(“三角形的面积:%.2f” % s)
else:
print(“a={},b={},c={}不能构成三角形。”.format(a, b, c))
例2:
键盘输入一个整数,判断是奇数还是偶数.
代码演示:
num = int(input(“请输入一个整数:”))

方法1:

if num % 2 == 0:
print(“偶数”)
else:
print(“奇数”)

方法2:

if num%2==0:
 print("偶数")

else:
print(“奇数”)

方法3:

if num%2!=0:
print(“奇数”)
else:
print(“偶数”)

方法4:

if num%21:
print(“奇数”)
else:
print(“偶数”)
python提供了一种简化的条件运算,条件运算符是一种三目运算符,它有3个运算对象,语法格式如下:
表达式1 if 表达式 else 表达式2
条件运算的规则:首先计算if后面表达式的值,如果值为True,则计算表达式1,并将表达式1的值作为条件运算的结果。否则将表达式2的值作为条件运算的结果。
x, y = 30, 90
res = x if x > y else y
print(“x和y中的最大值:”, res)
例3:
键盘输入一个三位数的整数,判断是否为水仙花。例如:153 它的13+53+3**3
153 因此是水仙花。
代码演示:

方法1:

num = int(input(“请输入三位数的整数:”))
a = num // 100 # 百位
b = num // 10 % 10
c = num % 10
if a ** 3 + b ** 3 + c ** 3 == num:
print(“{}是水仙花”)
else:
print(“{}不是水仙花”)
方法2:
num = input(“请输入三位数的整数:”)

153 “153”

百位 num[0]

十位 num[1]

个位 num[2]

if int(num[0])**3 + int(num[1])**3+int(num[2])**3==int(num):
print(“{}是水仙花”.format(num))
else:
print(“{}不是水仙花”.format(num))

4.6.3多分支选择结构
多分支选择结构用于处理多个条件、多个分支的情况,可以用if-elif-else语句来实现。语法格式如下:
if 表达式1:
语句块1
elif 表达式2:
语句块2
elif 表达式3:
语句块3
elif 表达式m:
语句块m
……
[else:
语句块 n]
if-elif-else 语句的执行流程如下:首先计算表达式1的值,如果表达式1的值为True,则执行语句块1,否则计算表达式2的值;如果表达式2的值为True,则执行语句块2,否则计算表达式3的值,以此类推。如果所有的表达式的值都为False,那么执行else后面的语句块n,整个执行流程图如下:

例1:
将成绩划分为4个等级:85分以上代表优秀,7084分代表良好,6069分为及格,60分以下为不及格。要求从键盘输入成绩后输出相应的等级。
代码演示:
score = eval(input(“请输入学生成绩:”))
if score < 60:
print(“不及格”)
elif score < 70:
print(“及格”)
elif score < 85:
print(“良好”)
else:
print(“优秀”)
例2:
18岁或以上:adult,6岁或以上:teenager,6岁以下:kid
age = int(input(“请输入年龄:”))
if age >= 18:
print(“adult”)
elif age >= 6:
print(“teenager”)
else:
print(“kid”)
例3:
键盘输入身高height(单位m)和体重weight(单位kg),按照公式:体重除以身高的平方来计BIM的值.如果BIM小于18.5则是过轻,18.5<=BIM<=25则是正常,25<BIM<=28则是过重,28<BIM<=32则是肥胖,BIM>32,则是严重肥胖。
height = float(input(‘请输入身高(m):’))
strong = float(input(‘请输入体重(kg):’))
BIM = strong / height ** 2
if BIM < 18.5
print(‘过轻’)
elif 18.5 <= BIM <= 25:
print(‘正常’)
elif 25 < BIM <= 28:
print(‘过重’)
elif 28 < BIM <= 32:
print(‘肥胖’)
else:
print(‘严重肥胖’)
4.6.4选择结构的嵌套
如果有多个条件并且条件之间存在递进关系,则可以在一个选择结构中嵌入另一个选择结构,形成选择结构的嵌套。在内部的选择结构中还可以继续嵌入选择结构,嵌套的深度是没有限制的。
其语法结构如下:

例1:
从键盘输入用户名和密码,然后对输入的用户名进行验证,如果用户名正确,再对输入的密码进行验证。
代码演示:

设置用户名和密码

USERNAME = “admin”
PASSWORD = “123456”

从键盘输入用户名

username = input(“请输入用户名:”)

验证用户名

if username == USERNAME:
# 从键盘输入密码
password = input(“请输入密码:”)
# 验证密码
if password == PASSWORD:
print(“登录成功!”)
else:
print(“密码错误!”)
else:
print(“用户名错误!”)
4.7 循环结构
循环结构是控制一个语句块重复执行的程序结构,由循环条件和循环体两部分组成,循环结构的特点是:在一定条件下重复执行某些语句,直至重复到一定次数或该条件不再成立为止。
4.7.1 for语句
for语句是一个通用的序列迭代器,可以用于遍历任何序列对象中的所有元素。语法格式如下:
for 循环变量 in 序列对象:
语句块(循环体)
[else:
语句块]
序列对象常见的有:字符串、列表、元组、集合、字典。
如果for循环正常结束才会执行else语句块,如果for语句块里面有break且执行了break子句而导致中断循环,则不会执行else子句。
例1:
使用for循环,找出1~10(包含10)之间的偶数.
for i in range(1, 11):
if i % 2 == 0:
print(i, end=" “)
例2:
键盘输入一个自然数,判断它是不是素数(素数只能被1或本身整除,2是最小的素数)
num = int(input(“请输入一个自然数:”))
flag = True # 默认是素数
if num >= 2:
for i in range(2, num):
if num % i == 0:
flag = False
break
if flag:
print(”{}是素数".format(num))
else:
print(“{}不是素数”.format(num))
else:
print(“输入有误!”)
4.7.1 while语句
While语句的功能是在满足指定条件时执行一个语句块,其语法格式如下:
While 表达式:
语句块(循环体)
[else:
语句块]
表达式的bool值为True,则执行循环体,直到表达式的bool值为False退出循环体。当循环体只包含单个语句时,也可以将该语句与while写在同一行;当循环体包含多个语句时,这些语句具有相同的缩进量。
这里else的语句块是否执行,取决于while循环里面是否正常退出,如果是break中断循环,则不会执行。
例1:
使用while打印出九九乘法表
代码演示:
i = 1
while i <= 9:
j = 1
while j <= i:
print(“{}*{}={}”.format(j, i, j * i), end=“\t”)
j += 1
print()
i += 1
例2:
使用while计算1~20的累加和
i = 1
s = 0
while i <= 9:
s += i
i += 1
print(s)
4.7.2 循环控制语句
1.break语句
break语句用来终止当前的循环,
break语句用在while和for循环中,通常与if语句一起使用,可以用来跳出当前所在的循环结构,即使循环还在执行,也会立即停止执行的循环语句,跳出循环体(如果有else子句,则不会执行),执行循环下面的语句。
例1:
计算前100个自然数之和
i, s = 1, 0
while True:
s += i
i += 1
if i == 101:
break
print(s)

例2:
从键盘连续输入数字进行累加,直到输入-1表示退出累加,输出累加和。
s = 0
while True:
num = int(input(“请输入数字(-1退出累加):”))
if num == -1:
break
s += num
print(“累加和:”, s)
2.continue语句
continue用于跳出本次循环,continue也是用在while和for循环中,通常也是与if语句一起使用,但是与break有所不同,continue语句用来跳出当前循环的剩余语句,然后继续执行下一轮循环,而break语句则是用于跳出整个循环。
例1:
展示continue与break的区别
for i in range(1, 10):
if i == 5:
continue
print(i, end=" “)
print()
for i in range(1, 10):
if i == 5:
break
print(i, end=” ")

例2:
输出1~80之间不能被5整除的整数,运行结果如下:

for i in range(1, 81):
if i % 5 == 0:
print()
continue
print(str(i), end=“\t”)
3.pass语句
为了保持程序结构的完整性,Python提供了一个空语句pass,pass语句一般仅作为占位语句,不做任何事。
例1:
for x in “python”:
if x == “h”:
pass
print(“在这里遇到了pass空语句”)
print(“当前字母:{}”.format(x))
print(“Over!”)

4.7.3 循环结构的嵌套
在一个循环结构中可以嵌套另一个循环结构,由此形成嵌套的循环结构,也称为多重循环结构。
如果在多重结构中使用break语句和continue语句,则这些语句仅作用于其所在层的循环。
输出九九乘法表:
1.使用while循环
i = 1
while i <= 9:
j = 1
while j <= i:
print(“{}{}={}“.format(j, i, j * i), end=”\t")
j += 1
print()
i += 1
2.使用for循环
for i in range(1, 10):
for j in range(1, i + 1):
print("{}
{}={}”.format(j, i, j * i), end=“\t”)
print()
3. 打印出下面的数组
“”"
1 2 3 4 5
2 3 4 5 1
3 4 5 1 2
4 5 1 2 3
5 1 2 3 4
“”"
for i in range(1,6):
for j in range(i,6):
print(j,end=" “)
for m in range(1,i):
print(m,end=” “)
print()
4. 计算下面的数列,前十项的和
2/1,3/2,5/3,8/5,13/8,21/13…
a, b = 2, 1
s = 0
for i in range(1, 11):
print(f”{a}/{b}")
s += a / b
a,b = a + b,a
print(s)
4.7.4 异常处理
异常是指程序运行期间出现错误或意外情况,一般情况下,在Python无法正常处理程序时就会发生一个异常,引发异常有各种各样的原因,例如命名错误、数据类型错误等。Python提供一套完整的异常处理方法,可以用来对各种可预见的错误进行提醒。
4.7.4.1 异常类
Python中常见的标准异常详见表:
BaseException类是所有异常的基类,而其子类Exception则是除SystemExit、KeyboardInterrupt和Generator这3个系统级异常之外的所有内置异常类和用户自定义异常类的基类。
异常名称 描述
BaseException 所有异常的基类
SystemExit 解释器请求退出
KeyboardInterrupt 用户中断执行(通常是由于按Ctrl+C组合键引起的)
Exception 常规错误的基类
ZeroDivisionError 在除法或取模运算中以0作为除数
IOError 输入/输出操作失败(基本上是无法打开文件)
OSError 操作系统错误
IndexError 序列中没有此索引
ImporError 导入模块对象失败(基本上是路径问题或名称错误)
NameError 未声明/初始化对象(没有属性)
SyntaxError Python语法错误
IndentationError 缩进错误
TypeError 类型错误(对类型无效的操作)
ValueError 传入无效的参数
UnicodeError Unicode相关的错误
4.7.4.2 try-except语句
可以用来检测try语句块中的错误,从而让except子句捕获异常并加以处理,这样就不会因为发生异常而导致程序中断运行。try-except语句可以分为单分支异常处理和多分支异常处理

  1. 单分支异常处理
    单分支异常处理的语法格式如下:
    try:
    语句块
    except:
    异常处理的语句块 # 发生异常时执行的操作
    try语句块里面有异常则会执行except里面的语句块,try语句块正常执行就不会执行except里面的语句块。直接执行后续的语句。
    例1:
    整数除法中的单分支异常处理
    x, y = eval(input(“请输入两个数字:”))
    try:
    z = x / y
    print(z)
    except:
    print(“程序发生异常!”)

我们可以将异常错误的类型打印出来

x, y = eval(input(“请输入两个数字:”))
try:
z = x / y
print(z)
except Exception as e:
print(“程序发生异常!”, e)
2. 多分支异常处理
多分支异常处理的语法格式如下:
try:
语句块
except 异常类1 [as 错误描述]:
异常处理语句块1
except 异常类2 [as 错误描述]:
异常处理语句块2

except 异常类n [as 错误描述]:
异常处理语句块n
except:
默认异常处理语句块
else:
语句块
多分支异常处理语句可针对不同的异常类型进行不同的处理,其执行流程如下:
执行try后面的语句块,如果未发生异常,则执行该语句块后执行else后面的语句块,然后执行try-ecxept语句的后续语句;如果引发异常,则依次检查各个except语句,试图找到匹配的异常类型;如果找到了,则执行相应的异常处理语句块;如果未找到,则执行最后一个except语句中的默认异常处理语句块,异常处理完成后执行try-except语句的后续语句。
例1:
整数除法中的多分支异常处理
x, y = eval(input(“请输入两个数字:”))
try:
z = x / y
print(z)
except TypeError as te:
print(“数据类型错误!”, te)
except ZeroDivisionError as zde:
print(“0不能作为除数!”, zde)
except:
print(“程序发生异常!”)
else:
print(“程序正常结束.”)
4.7.4.3 try-finally语句
try-finally语句用于指定无论是否发生异常都会执行的代码,其语法格式如下:
try:
语句块
except:
异常处理语句块
else:
语句块
finally:
语句块
例1:
整数除法中的异常处理,展示finally子句的应用示例:
x, y = eval(input(“请输入两个数字:”))
try:
z = x / y
print(z)
except Exception as e:
print(“程序发生异常!”,e)
else:
print(“程序正常结束.”)
finally:
print(“执行finally子句”)
如果在try子句中发生异常,但是异常没有被except子句处理,或者在except或else子句中发生了异常,则在finally子句执行完后会将异常依旧会引发。
章节习题

4.8数据结构
4.8.1字符串
字符串是python内置的有序序列,字符串是一种不可变的对象,字符串中的字符是不能被改变的,每当修改字符串时都将生成一个新的字符串对象,对于字符串可以进行各种操作,主要包括通过索引访问指定位置的单个字符,通过切片从给定的字符串中获取子串,将两个或多个字符串连接成一个新的字符串,对两个字符串进行比较,使用for循环遍历字符串。
4.8.1.1 字符串的索引
访问字符串上的指定字符,其语法格式如下:
字符串[索引]
举例说明:S=“python”
S[0] S[1] S[2] S[3] S[4] S[5]
p y t h o n
S[-6] S[-5] S[-4] S[-3] S[-2] S[-1]
从上面可以看出:
最后一个字符的索引为-1
当索引为正整数,那么最后一个字符的索引是字符串的长度减1
求字符串的长度使用内置函数len( )求出。
无论使用正向索引还是反向索引,索引值都不能越界。否则将会出现错误信息”IndexError:string index out of range”,即字符串索引超出范围。

s=“Hello Python”
s[0]
‘H’
s[1]
‘e’
s[-1]
‘n’
s[-2]
‘o’
s[12]
Traceback (most recent call last):
File “”, line 1, in
IndexError: string index out of range

因为字符串属于不可变对象,所以索引只能读取字符串指定位置上的字符,而不能修改该位置上的字符。即字符串不支持赋值操作。
例1:
从键盘输入一个字符串,然后以相反顺序输出该字符串。
s = input(“请输入字符串:”)
i = -1
while i >= -len(s):
print(s[i], end=“”)
i -= 1

for循环

str1 = input(“请输入字符串”)
n = len(str1)
str2 = “” # 空字符串
for i in range(1, n + 1):
str2 += str1[-i]
print(str2)

陈氏法

str1 = “hello”
n = len(str1)
str2 = “”
for i in range(-1, -n - 1, -1):
str2 += str1[i]
print(str2)

4.8.1.2 字符串的切片
如果要从字符串中提取一部分字符串(子串),则可以通过切片(slice)操作来实现,其一般语法格式如下:
字符串对象[开始位置:结束位置:步长]
步长默认为1,不包含结束位置。

s=“python language”
s[1:10:1]
‘ython lan’
s[1:10:2]
‘yhnln’
s[:5] # 取出索引为0~4的字符
‘pytho’
s[2:] # 从索引为2的字符开始,直至字符串结束
‘thon language’
s[:] #取出所有字符
‘python language’
s[::] #取出所有字符
‘python language’
s[::2] # 步长为2,隔一个取一个
‘pto agae’
s[::-1] # 步长为-1,逆序取出所有字符
‘egaugnal nohtyp’
s[:100] # 结束位置越界,切片到字符串结束
‘python language’
s[100:] # 开始位置越界,返回空字符串
‘’

由于字符串是不可变对象,因此不能对字符串切片赋值,否则会出现错误信息: TypeError: ‘str’ object does not support item assignment.
4.8.1.3 字符串的连接
字符串的连接可以使用加法运算符”+”或乘法运算符”*”来实现。
加法运算符可以将两个字符串连接成一个新的字符串,乘法运算符可以将一个字符串自身重复连接若干次形成一个新的字符串。
1.基本连接
在python中,“+”运算符有3个作用:
A:作为双目运算符用于数值对象,进行加法运算
B:作为单目运算符,表示正号
C: 作为双目运算符用于字符串对象,进行字符串的连接
运算符”+”作为字符串连接运算符使用时,可以将字符串常量、字符串变量以及返回字符串的函数表达式等字符串数据进行连接。
运算符”+”两侧必须是相同数据类型,若将字符串与数值连接,就需要用内置函数str( )将数值转为字符串。例如:

str(2022)+”年”+str(5)+”月”
2.重复连接
在python中,“”运算符有2个作用:
A:作为双目运算符用于数值对象,进行乘法运算
B: 作为双目运算符用于字符串和正整数对象,进行字符串的重复连接操作。
重复连接的语法:
字符串
正整数 (正整数字符串)
其中字符串可以是字符串类型的常量、变量或函数,正整数用于指定这个字符串重复连接的次数。
举例:
str1 = “python”
str1
3
‘pythonpythonpython’
3*str1
‘pythonpythonpython’
“5”*3
‘555’
例1:
从键盘连续循环输入,当输入quit退出循环,后将连续输入的单词组成句子。
sentence = “”
while True:
word = input(“请输入单词(输入quit退出):”)
if word == “quit”:
break
sentence += " " + word
print(“组成的句子:{}.”.format(sentence))
4.8.1.4字符串的关系运算
字符串的关系运算主要包括:1.字符串比较. 2.成员运算符in来判断一个字符串是不是另外一个字符串的子串。
1.比较字符串
将两个字符串从左向右逐个进行比较,直到比较出哪边对应的字符ASCII值大则哪边的字符串大。
“hello”>“hellp”
False
“abc”>“bbc”
False
“abc”>“bad”
False
比较两个长度不相同的字符串时,首先在较短的字符串尾部补上一些空格字符,使两个字符串具有相同的长度,然后再使用上面的规则进行比较。
2.判断子串
使用成员运算符判断一个字符串是否为另一个字符串的子串。
‘yt’ in ‘python’
True
‘mn’ in ‘python’
False
例2:
从键盘输入两个字符串,比较它们的大小并判断第一个字符串是不是第二个字符串的子串。
str1 = input(“请输入第一个字符串:”)
str2 = input(“请输入第二个字符串:”)

比较字符串

if str1 == str2:
print(“{}等于{}”.format(str1, str2))
elif str1 > str2:
print(“{}大于{}”.format(str1, str2))
else:
print(“{}小于{}”.format(str1, str2))

判断子串

if str1 in str2:
print(“{}是{}的子串”.format(str1, str2))
elif str2 in str1:
print(“{}是{}的子串”.format(str2, str1))
else:
print(“{}和{}没有子串的关系”.format(str1, str2))

4.8.2字符串的常用方法
4.8.2.1 字母大小写转换
若要进行字母的大、小写转换,则可以通过以下方法返回一个新字符串。
str.upper() 全部转为大写
str.lower() 全部转为小写
str.swapcase() 大小写互换
str.capitalize() 整个字符串的首字母变成大写,其余字母变成小写。
str.title() 每个单词的首字母大写,其余字母均为小写

str = “hello WORLD”
print(str.upper()) # HELLO WORLD
print(str.lower()) # hello world
print(str.swapcase()) # HELLO world
print(str.capitalize()) # Hello world
print(str.title()) # Hello World

整个字符串的首字母变成大写,其余字母变成小写

str1 = input(“请输入一个语句:”)

取出第一个字符并转为大写

str1_1 = str1[0].upper()

将第一个字符和后面的所有字符进行拼接

print(str1_1 + str1[1:])

每个单词的首字母大写,其余字母均为小写

str1 = input(“请输入一个语句:”)
list_word = str1.split()
words = “” # 空字符串用于后面的字符串拼接
for word in list_word:
word_1 = word[0].upper() # 首字母大写
word_2 = word[1:].lower() # 其余字母均为小写
new_word = word_1 + word_2
words += new_word + " "
print(words)

4.8.2.1 字符串中的搜索和替换
1.str.find(substr,[,start,end]) 用于检测substr 是否在str中,若在则返回开始的索引值,否则返回-1,若用start和end指定范围,则在str[start:end]中搜索。
str1 = “hello python”
print(str1.find(“llo”)) # 2
print(str1.find(“llo”, 5, 8)) # -1
2.str.index(substr,[,start,end]) 用法与find()相同,只是当substr不在str中会报一个异常。
str1 = “hello python”
print(str1.index(“llo”)) # 2
print(str1.index(“llo”, 5, 8)) # ValueError: substring not found
3.str.rfind(substr,[,start,end]) 用法与find()相同,只是从右边开始查找。
str1 = “hello python llo”
print(str1.rfind(“llo”)) # 13
print(str1.rfind(“llo”, 5, 8)) # -1
4.str.rindex(substr,[,start,end])用法与index()相同,只是当substr不在str中会报一个异常。
str1 = “hello world wor”
print(str1.rindex(“wor”)) # 12
print(str1.rindex(“op”)) # ValueError: substring not found
5.str.count(substr,[,start,end])用于返回substr在str中出现的次数,若用start和end指定范围,则返回在str[start:end]中出现的次数。
str1 = “hello world world”
print(str1.count(“world”)) # 2
print(str1.count(“o”)) # 3
print(str1.count(“o”, 5, 20)) # 2
print(str1.count(“o”, 5, )) # 2
print(str1.count(“o”, 20, 30)) # 0
print(str1.count(“o”, 20, )) # 0
6.str.startswith(prefix,[,start,end])用于检查字符串是否以prefix开头,若是则返回True,否则返回False.如果用start和end指定范围,则在该范围内检查。
str1 = “hello python”
print(str1.startswith(“h”)) # True
print(str1.startswith(“hel”)) # True
print(str1.startswith(“hello”)) # True
print(str1.startswith(“hellop”)) # False
print(str1.startswith(“py”, 6, 20)) # True
print(str1.startswith(“py”, 6, )) # True
7.str.endswith(suffix,[,start,end]) 用于检查字符串是否以suffix结尾,若是则返回True,否则返回False.如果用start和end指定范围,则在该范围内检查。
str1 = “hello python”
print(str1.endswith(“n”)) # True
print(str1.endswith(“on”)) # True
print(str1.endswith(“python”)) # True
print(str1.endswith(“pthon”)) # False
print(str1.endswith(“n”, 0, 20)) # True
print(str1.endswith(“py”, 0, 6)) # False
4.8.2.2 字符串的拆分和组合
1.str.split(sep[,num])以sep为分隔符将str拆分成列表,默认的分隔符为空格;num指定拆分的次数,默认值为-1,表示无限制拆分。
str1 = “helpo worpold”
print(str1.split()) # 默认以空格分隔
print(str1.split(“po”)) # 分隔的对象有几个就分隔几个,无限制
print(str1.split(“po”, 1)) # 限制分隔一次,并且是自左向右
2.str.rsplit(sep[,num])与split()类似,只是从右边开始拆分
str1 = “hello worldllo”
print(str1.rsplit(“llo”)) # 如果没有分隔限制,那和split()没有什么差异。
print(str1.rsplit(“llo”, 1)) # 如果有分隔限制,从右边开始分隔。
3.s.join(seq)以s作为分隔符,将序列seq中的所有元素合并成一个新的字符串。
str1 = “hello”
print("".join(str1)) # hell*o
4.8.2.3 字符串内容的测试
1.str.isalnum( ):字符串str中全是字母或数字,则返回True,否则返回False
str1 = “hello123”
print(str1.isalnum()) # True
str1 = “hello123!”
print(str1.isalnum()) # False
2.str.isalpha( ):字符串str中全是字母则返回True,否则返回False.
str1 = “hello123”
print(str1.isalpha()) # False
str1 = “hello”
print(str1.isalpha()) # True
3.str.isdecimal( ):字符串str中只包含十进制的数字则返回True,否则返回False.
str1 = “0b1010”
print(str1.isdecimal()) # False
str1 = “123”
print(str1.isdecimal()) # True
str1 = “123hello”
print(str1.isdecimal()) # False
4.str.isdigit( ):字符串str中只包含数字则返回True,否则返回False.
str1 = “0b1010”
print(str1.isdigit()) # False
str1 = “123”
print(str1.isdigit()) # True
str1 = “123hello”
print(str1.isdigit()) # False
5.str.islower( ):字符串str中的字母全是小写字母,则返回True,否则返回False.
str1 = “hello World”
print(str1.islower()) # False
str1 = “hello world”
print(str1.islower()) # True
str1 = “hello world123你好”
print(str1.islower()) # True
6.str.isupper( ):字符串str中的字母全是大写字母,则返回True,否则返回False.
str1 = “hello World”
print(str1.isupper()) # False
str1 = “HELLO WORLD”
print(str1.isupper()) # True
str1 = “HELLO WORLD123你好”
print(str1.isupper()) # True
7.str.isspace( ):字符串str中只包含空格,则返回True,否则返回False.
str1 = "hello "
print(str1.isspace()) # False
str1 = " "
print(str1.isspace()) # True
8.str.isascii( ):判断是否不含中文,没有中文返回True,有中文返回False
str1 = “hello world123%@”
print(str1.isascii()) # True
str1 = “hello world123%@你好”
print(str1.isascii()) # False

4.9数据结构
4.9.1列表
列表(list)可变的数据类型,是一个容器,可以存放任意数据类型,里面的每一个数据项称为一个元素。
4.9.1.1创建列表的方法
1.使用list( )内置函数来创建列表,可以将字符串、元组或其他可迭代对象类型转为列表,例如:
list1 = [] # 创建空列表的方法1
list2 = list() # 创建空列表的方法2
print(list1, list2)
str1 = “hello”
print(list(str1))
tup1 = (1, 2, 3, 4)
print(list(tup1))
set1 = (4, 5, 6, 7)
print(list(set1))
dict1 = {“hello”: 1, “world”: 2}
print(list(dict1))
print(list(dict1.keys())) # 默认将字典的键转为列表的元素
print(list(dict1.values()))
print(list(dict1.items()))
4.9.1.2列表的基本操作
1.通用操作

  1. 索引 通过索引对列表中的元素进行访问,语法格式如下:
    列表名[索引] 索引不能越界,否则会出现IndexError的错误
    元素的索引取值和字符串的索引取值原理一样。请参考前面的4.8.1.1 字符串的索引
  2. 切片 通过切片操作可以从列表中取出某个范围的元素.从而构成新的列表。语法格式如下:
    列表名[起始索引:终止索引:步长]
    步长默认值为1,如果步长为正数,则从左向右提取元素,如果步长为负数,则从右向左提取元素。

x=[1,2,3,4,5]
x[1:4]
[2, 3, 4]
x[1:6:2]
[2, 4]
x[0:6:2]
[1, 3, 5]
x[1:5:-1]
[]
x[-1:-5:-1]
[5, 4, 3, 2]
x[5:1:-1]
[5, 4, 3]
3)加法连接 语法格式如下:
列表1+列表2
[1,2,3]+[4,5,6]
[1, 2, 3, 4, 5, 6]
4)乘法连接 语法格式如下:
列表整数 或 整数列表
[1,2,3]3
[1, 2, 3, 1, 2, 3, 1, 2, 3]
2
[“AB”,“CD”]
[‘AB’, ‘CD’, ‘AB’, ‘CD’]
5)比较两个列表 比较的规则如下:首先比较两个列表的第一个元素,如果这两个元素相等,则继续后面的对应的两个元素;如果这两个元素不相等,则返回这两个元素的比较结果。重复这个过程,直至出现不相等的元素或比较完所有元素为止.
[1,2,3,4]<[1,2,1,2,3]
False
[2,5,8]>[1,2,6,1]
True
6)检查成员资格 使用in 运算符可以判断一个值是否包含在列表中,语法格式如下:
值 in 列表
1 in [1,2,3]
True
9 in [1,2,3]
False
6 not in [1,2,3]
True
[1] in [1,2,3] # 将[1]看作整体
False
[1] in [[1],2,3]
True
7)遍历列表 要访问列表中的每个元素,可以通过while和for循环来实现。

使用while循环遍历列表元素

list1=[1,2,3,4,5]
n = len(list1)
i=0
while i<=len(list1)-1:
print(list1[i])
i+=1

使用for循环遍历列表元素

n = len(list1)
for i in range(0,n):
print(list1[i])
8)拆分赋值 例如:
x,y,z = [1,2,3]
print(x,y,z)
当进行拆分赋值时,要求变量个数必须与列表元素个数相等,否则会出现ValueError的错误,当变量个数小于列表个数时,可以在变量名前面加星号"*",这样会将多个元素赋值给相应的变量,例如:
x, *y, z = [1, 2, 3, 4, 5, 6]
print(x) # 1
print(y) # [2,3,4,5]
print(z) # 6
2.专用操作
列表对象是可变的序列,对列表除了可以使用序列的通用操作,还可以进行一些专用的操作,例如元素赋值、切片赋值、元素删除等。
1)元素赋值
lst = [1, 2, 3, 4]
lst[1] = 100
lst[2] = 200
print(lst)
2)切片赋值
通过切片赋值可以使用一个值列表来修改指定范围的一组元素的值。
当提供的值列表长度等于切片的长度,对应的值会被修改。

list1=[1,2,3,4,5,6]
list1[1:4] = [200,300,400]
list1
[1, 200, 300, 400, 5, 6]

当提供的值列表长度不等于切片的长度,对应的值会被修改。
1.如果提供的值列表长度大于切片的长度,则会插入新的元素。例如:

list1=[1,2,3,4,5,6]
list1[1:4]=[120,130,140,150,160]
list1
[1, 120, 130, 140, 150, 160, 5, 6]

2.如果提供的值列表长度小于切片的长度,则会删除多出的元素。例如:

list1=[1,2,3,4,5,6]
list1[1:4]=[200,300]
list1
[1, 200, 300, 5, 6]

3.当进行切片赋值的时候,如果步长不等于1,则要求提供的值列表长度必须与切片长度相等,否则将出现ValueError错误,例如:

list1=[1,2,3,4,5,6,7,8,9,10]
list1[0:10:2]=[11,22,33,44,55]
list1
[11, 2, 22, 4, 33, 6, 44, 8, 55, 10]
list1[0:10:2]=[100,200,300]
Traceback (most recent call last):
File “”, line 1, in
ValueError: attempt to assign sequence of size 3 to extended slice of size 5
3)元素删除 从列表中删除指定的元素,可以使用del语句来实现。例如:
list1=[1,2,3,4,5,6]
del list1[2]
list1
[1, 2, 4, 5, 6]

若要从列表删除指定范围内的元素,也可以通过切片赋值来实现,例如:

list1=[1,2,3,4,5,6]
list1[1:4]=[]
list1
[1, 5, 6]
4)列表推导式【列表解析】
可以通过列表推导式快速高效的创建新的列表.有两种语法格式:
[表达式 for 迭代变量 in 可迭代对象]
[表达式 for 迭代变量 in 可迭代对象 if 条件表达式]
例如:列出1~10所有数字的平方
list1=[ii for i in range(1,11)]
list1
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
如要列出1~10中能被2整除的数的平方
list1=[i
i for i in range(1,11) if i%2==0]
list1
[4, 16, 36, 64, 100]
4.9.1.3列表的常用函数
1适用于序列对象的内置函数
为了便于使用列表,Python提供了一些内置函数,这些函数不仅可以应用于列表,还可以应用于其他可迭代类型,例如字符串、元组等。

  1. len( ) 返回序列的长度 既序列中包含的元素个数 例如:

list1=[1,2,3,4,5]
len(list1)
5

  1. max( ) 返回序列中的最大元素,例如:

list1=[1,2,3,4,5]
max(list1)
5
当列表中的元素是字符,则返回ASCII最大的元素
list1=[“a”,“b”,“c”]
max(list1)
‘c’
当列表中的元素是字符串,则返回元素的首字符ASCII最大的元素
list1=[“hello”,“world”,“python”]
max(list1)
‘world’

  1. min( ) 返回序列中的最小元素,例如:

list1=[1,2,3,4,5]
min(list1)
1
当列表中的元素是字符,则返回ASCII最小的元素
list1=[“a”,“b”,“c”]
min(list1)
‘a’
当列表中的元素是字符串,则返回元素的首字符ASCII最小的元素
list1=[“hello”,“world”,“python”]
min (list1)
‘hello’

  1. sorted(iterable,key=None,reverse=False )对可迭代对象进行排序操作并返回排序后的新列表,原始列表不变,参数iterable表示可迭代类型,参数key指定一个函数,实现自定义排序,默认为None,参数reverse用于指定规则,设置为True则按降序排序,默认为False的话表示按升序排序。例如:

list1=[10,3,1,2,6,4]
list2=sorted(list1)
list2
[1, 2, 3, 4, 6, 10]
list2=sorted(list1,reverse=True)
list2
[10, 6, 4, 3, 2, 1]

  1. sum(iterable[,start]) 对序列进行求和计算,参数iterable表示可迭代类型;start是可选项,用以指定相加的参数,默认为0,例如:

list1=[1,2,3,4]
sum(list1)
10
sum(list1,10)
20
例1:
从键盘连续输入数字,当输入字母q或者Q表示退出循环。退出循环后计算出数字的累加和。并求出输入的数字的最大值,最小值,并将输入的数字按照从大到小的顺序进行排序。
s = 0
list1 = []
while True:
num = input(“请输入数字:”)
if num == “q” or num == “Q”:
break
num = int(num) # 将字符串类型的数字转为整型数据
list1.append(num)
s += num
print(“数字的累加和:”, s)
print(“输入的数字最大值:”, max(list1))
print(“输入的数字最小值:”, min(list1))
list2 = sorted(list1, reverse=True)
print(“输入的数字从大到小的顺序:”,end=" “)
for i in list2:
print(i, end=” ")
2适用于序列对象的成员方法

  1. lst.append(x) 使用该方法可以在列表lst末尾添加元素x,等价于执行复合赋值语句lst+=[x].列如:

lst=[“C”,“Python”,“PHP”]
lst.append(“Java”)
lst
[‘C’, ‘Python’, ‘PHP’, ‘Java’]

  1. lst.extend(L) 使用该方法可以在列表lst末尾添加另一个列表,等价于执行复合赋值语句lst+=L 例如:

lst=[“C”,“Python”,“PHP”]
lst.extend([“Java”,“Go”])
lst
[‘C’, ‘Python’, ‘PHP’, ‘Java’, ‘Go’]

  1. lst.insert(i,x)使用该方法可以在列表lst的i位置插入元素x,如果i大于列表的长度,则将元素x插入到列表末尾。例如:

lst=[1,2,3]
lst.insert(1,100)
lst
[1, 100, 2, 3]
lst.insert(5,100)
lst
[1, 100, 2, 3, 100]

  1. lst.remove(x) 使用该方法可以从列表lst中删除第一个值为x的元素,如果列表中不存在这样的元素则会出现ValueError错误,例如:

lst=[1,2,3,4,5,6,2]
lst.remove(2)
lst
[1, 3, 4, 5, 6, 2]
lst.remove(7)
Traceback (most recent call last):
File “”, line 1, in
ValueError: list.remove(x): x not in list

  1. lst.pop(i) 使用该方法可以从列表lst中弹出索引为i的元素,然后删除并返回该元素;如果未指定参数i,则会弹出列表中的最后一个元素;如果指定的参数i越界,则会出现IndexError的错误,例如:

lst=[1,2,3,4,5,6]
lst1=lst.pop(3)
lst1
4
lst
[1, 2, 3, 5, 6]
lst.pop()
6
lst
[1, 2, 3, 5]

  1. lst.count(x) 使用该方法可以返回元素x在列表lst中出现的次数。例如:

list1=[1,2,3,4,2,5,2]
list1.count(2)
3

  1. lst.index(x[,start,end]) 使用该方法返回元素x在列表lst中第一次出现的索引值,如果元素x未包含在列表lst中,则会出现ValueError的错误。例如:

lst=[“a”,“b”,“c”,“d”,“b”]
lst.index(“b”)
1
lst.index(“e”)
Traceback (most recent call last):
File “”, line 1, in
ValueError: ‘e’ is not in list

  1. lst.sort(key=None,reverse=True)使用该方法可以对列表lst进行排序,使用该方法会修改原列表,若要返回一个新的列表而不修改原列表,使用内置函数sorted( )。例如:

lst=[10,2,4,3,1,6,7,5]
lst.sort()
lst
[1, 2, 3, 4, 5, 6, 7, 10]
lst.sort(reverse=True)
lst
[10, 7, 6, 5, 4, 3, 2, 1]

  1. lst.reverse( ) 使用该方法可以反转列表list中所有元素。例如:

lst=[3,6,8,1,9,2]
lst.reverse()
lst
[2, 9, 1, 8, 6, 3]

  1. lst.copy( ) 使用该方法可以复制列表list中所有元素。例如:
    list1 = [1, 2, 3, 4, 2]
    list2 = list1.copy()
    list2.reverse()
    print(list1)
    print(list2)
    例2:
    从键盘输入一个正整数,然后以该整数作为长度生成一个列表并用随机数对列表元素进行初始化,然后用列表对象的成员方法对该列表进行各种操作。
    4.9.2 元组
    在python中,元组(tuple)与列表类似,它们同属于有序的序列类型。不同的是元组是不可变对象,元组一经创建,其元素便不能被修改。
    4.9.2.1 元组的基本操作
    元组的元素用逗号隔开,放在圆括号内。
    注意:当元组中只包含一个元素时,需要在元素后面添加逗号,以防运算时被当作括号。

tup1=(1)
print(type(tup1))
<class ‘int’>
tup1=(1,)
print(type(tup1))
<class ‘tuple’>
可以通过调用tuple( )函数来创建元组,通过调用tuple( )函数还可以将字符串和列表、集合、字典转为元组。例如:
tup1=tuple() # 创建空的元组
tup1
()
tup2=tuple(“hello python”)
tup2
(‘h’, ‘e’, ‘l’, ‘l’, ‘o’, ’ ', ‘p’, ‘y’, ‘t’, ‘h’, ‘o’, ‘n’)
tup3 = tuple([1,2,3,4,5,6])
tup3
(1, 2, 3, 4, 5, 6)
set1 = {1, 2, 3, 4}
print(tuple(set1))

dict1 = {“world”: 1, “hello”: 2}
print(tuple(dict1))
print(tuple(dict1.keys()))

print(tuple(dict1.values()))
print(tuple(dict1.items()))
可以对元组进行加法和乘法运算
使用索引访问元组指定位置的元素
通过切片从元组中获取部分元素
使用关系运算符比较两个元组
使用成员运算符in来判断某个值是否存在于元组中
使用for循环遍历元组
使用内置函数len( )计算元组的长度等
由于元组是不可变对象,是不允许修改元组中的元素值,如果试图通过赋值语句修改元组中的元素,将会出现TypeError的错误,同样,是不允许删除元组中的元素的。但是可以使用del语句来删除整个元组。
例1:
元组基本操作示例:
4.9.2.1 元组封装与序列拆封
1.元组封装
元组封装是指以逗号分隔的多个值自动封装到一个元组中,例如:

x = “vb”,“python”,“java”
x
(‘vb’, ‘python’, ‘java’)
type(x)
<class ‘tuple’>
2.序列拆封
序列拆封是元组封装的逆运算,可以用来将一个封装起来的元组对象自动拆分成若干个基本数据。例如:
x,y,z = (1,2,3)
print(x,y,z)
1 2 3
上面的序列拆分操作要求赋值运算符左边的变量数目与右边序列中包含的数据数目相同,否则会出现ValueError错误!
封装操作只能用于元组对象,而拆分操作不仅可以用于元组对象,还可以用于序列对象。
例1:
输入两个字符串并将其存入两个变量,然后交换两个变量的内容。
s1 = input(“请输入第一个字符串:”)
s2 = input(“请输入第二个字符串:”)
print(“s1={} s2={}”.format(s1, s2))
s1, s2 = s2, s1
print(“交换后的字符串”)
print(“s1={} s2={}”.format(s1, s2))

列表和元组之间可以互相转换
元组转列表使用内置函数list( )
列表转元组使用内置函数tuple( ) 请看下面的示例:

tuple1=(“hello”,“python”,1,2)
list1=list(tuple1)
list1
[‘hello’, ‘python’, 1, 2]
tuple2 = tuple(list1)
tuple2
(‘hello’, ‘python’, 1, 2)

4.9.3 集合
集合是一些不重复的无序组合,集合分为可变集合和不可变集合。集合不记录元素的位置,因为对集合不能进行索引和切片等操作。
4.9.3.1 创建集合
4.9.3.1.1创建可变集合
创建可变集合的最简单方法是使用逗号分隔一组数据并将他们放在一对花括号中。

set1={1,2,3,4,5,6}
type(set1)
<class ‘set’>
集合中的元素可以是不同的数据类型,但是不能是可变的数据类型(列表,字典)因为集合的三大特征(确定性、互异性、无序性)中的确定性决定的。
set1={1,2,3,“hello”,“python”}
set1
{1, 2, 3, ‘hello’, ‘python’}
set2={1,2,[1,2,3]}
Traceback (most recent call last):
File “”, line 1, in
TypeError: unhashable type: ‘list’
set3={1,2,3,{“hello”:1}}
Traceback (most recent call last):
File “”, line 1, in
TypeError: unhashable type: ‘dict’
集合中不能包含重复的元素,因为集合的三大特征(确定性、互异性、无序性)中的互异性决定的。如果创建可变集合时使用了重复的数据,Python会自动删除重复的元素,例如:
set1={1,2,3,4,5,1,2}
set1
{1, 2, 3, 4, 5}
可变集合使用内置的set类来定义,使用集合类的构造函数set( )可以将字符串、列表和元组等类型转换为可变集合。例如:
set1=set()
set1
set()
set2=set([1,2,3,4,5,6])
set2
{1, 2, 3, 4, 5, 6}
set3=set((1,2,3,4,5,6))
set3
{1, 2, 3, 4, 5, 6}
set4=set((i for i in range(10)))
set4
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
创建空集合只能使用set( )而不能使用{ },如果使用{ },则会创建一个空字典.
set1=set()
type(set1)
<class ‘set’>
set2={}
type(set2)
<class ‘dict’>
4.9.3.1.2可变集合的操作
下列方法会修改原集合的内容,仅适用于可变集合.
1.set1.add(x) 该函数用于在集合set1中添加元素x,如:
set1={1,2,3,4,5,6}
set1.add(7)
set1
{1, 2, 3, 4, 5, 6, 7}
2.set1.update(set2,set3,…,setn)该函数把集合set2,set3,…setn拆分成单个数据项并将其添加到集合set1中,如下:
set1={1,2,3}
set1.update({4,5,6},{7,8,9})
set1
{1, 2, 3, 4, 5, 6, 7, 8, 9}
3.set1.remove(x) 该函数用于从集合set1中删除元素x,若x不存在于集合set1中,则会出现KeyError的错误。例如:
set1={1,2,3,4,5}
set1.remove(4)
set1
{1, 2, 3, 5}
set1.remove(6)
Traceback (most recent call last):
File “”, line 1, in
KeyError: 6
4.set1.pop( )该函数用于从集合set1中弹出一个元素,即删除并返回该元素,例如:
set1={1,2,3,4,5,6}
set1.pop()
1
set1.pop()
2
set1.pop()
3
set1.pop()
4
set1.pop()
5
set1.pop()
6
set1.pop()
Traceback (most recent call last):
File “”, line 1, in
KeyError: ‘pop from an empty set’
set1
set()
5.set1.clear( )该函数用于删除集合set1中的所有元素。例如:
set1={1,2,3}
set1.clear()
set1
set()
2.创建不可变集合
不可变集合可以调用frozenset( )函数来创建,格式如下:
frozenset([iterable])
其中的参数iterable为可选项,用于指定一个可迭代对象,例如列表、元组、可变集合、字典等。如果不提供参数,则会生成一个空集合。例如:
fz1=frozenset(range(10))
fz1
frozenset({0, 1, 2, 3, 4, 5, 6, 7, 8, 9})
fz2=frozenset(“hello”)
fz2
frozenset({‘o’, ‘e’, ‘h’, ‘l’})
fz3=frozenset()
fz3
frozenset()
4.9.3.2 可变和不可变集合的通用操作
1.集合的并入
对于可变和不可变的集合,可以使用运算符”|=”将一个集合并入另外一个集合中,A|=B 就是将集合B并入集合A例如:
set1={1,2,3}
set2={4,5,6}
set1|=set2
set1
{1, 2, 3, 4, 5, 6}
fz1=frozenset((1,2,3))
fz2=frozenset((4,5,6))
fz1|=fz2
fz1
frozenset({1, 2, 3, 4, 5, 6})
2.集合的遍历
使用for循环可以遍历集合中的所有元素。例如:
set1 = {7,5,2,1}
for i in set1:
print(i, end=" “)
print()
fz1 = frozenset((5,3,1,2))
for i in fz1:
print(i, end=” ")

4.9.3.2.1 集合运算
计算交集 两个集合共有的元素组成的集合,使用运算符”&”计算两个集合的交集。例如:

set1={1,2,3,4,5}
set2={3,4,5,6,7}
set1&set2
{3, 4, 5}
计算并集 两个集合所有元素的集合,使用运算符”|”计算两个集合的并集。例如:

set1={1,2,3,4,5}
set2={3,4,5,6,7}
set1|set2
{1,2,3, 4, 5,6,7}
计算差集 A-B表示属于集合A但不属于集合B的元素所组成的集合称为集合A和集合B的差集 B-A表示属于集合B但不属于集合A的元素所组成的集合称为集合B和集合A的差集例如:

set1={1,2,3,4,5}
set2={3,4,5,6,7}
set1-set2
{1, 2}
set2-set1
{6, 7}
对称差集 对于集合A和B,由所有属于集合A但不属于集合B,属于集合B但不属于集合A的元素所组成的集合称为集合A和集合B的对称差集,可以使用运算符”^”计算两个集合的对称差集。例如:

set1={1,2,3,4,5}
set2={3,4,5,6,7}
set1^set2
{1, 2, 6, 7}
例1:
从键盘输入一些数字组成两个集合,然后使用相关运算符计算这两个集合的交集、并集、差集以及对称差集。
tup1 = eval(input(“请输入一些数字组成第一个集合:”))
tup2 = eval(input(“请输入一些数字组成第二个集合:”))
set1 = set(tup1)
set2 = set(tup2)
print(“创建的两个集合如下:”)
print(“set1={}”.format(set1))
print(“set2={}”.format(set2))
print(“集合运算结果如下:”)
print(“set1与set2的交集:”,set1&set2)
print(“set1与set2的并集:”,set1|set2)
print(“set1与set2的差集:”,set1-set2)
print(“set1与set2的对称差集:”,set1&set2)
例2:
从键盘输入一些数字组合成一个集合,然后通过调用集合对象的相关方法对该集合进行修改。
tup1 = eval(input(“请输入一些数字组成第一个集合:”))
tup2 = eval(input(“请输入一些数字组成第二个集合:”))
set1 = set(tup1)
set2 = set(tup2)
print(“创建的集合如下:”)
print(“set1={}”.format(set1))
print(“set2={}”.format(set2))
set1.add(“hello”)
print(“添加元素后的集合set1={}”.format(set1))
set1.update(set2)
print(“将集合set2的元素添加到集合set1中:”, set1)
x = int(input(“请输入要删除的元素:”))
set1.remove(x)
print(“删除元素后的set1”, set1)
set1.clear()
print(“清空set1中的元素:”, set1)
4.9.4 字典
字典(dict)是由一组键(key)及与其对应的值构成的,键与对应的值之间用冒号分隔,键与值放置在一对花括号内。在同一个字典中,键与值之间存在一一对应的关系。键的作用相当于索引,每个键对应的值就是数据。字典属于可变数据类型,在字典中可以包含任何数据类型。
4.9.4.1 创建字典
创建字典的一般语法格式如下:
字典名={键1:值1,键2:值2, 键3:值3…}
键是不可变类型,例如整数、字符串、元组等。键必须是唯一的。值可以是任意数据类型,可以不是唯一的。如果花括号内提供任何元素,则会生成一个空字典。
dict1={}
type(dict1)
<class ‘dict’>
dict2={“name”:“张三”,“age”:18}
dict2
{‘name’: ‘张三’, ‘age’: 18}
dict2={[1,2,3]:“张三”,“age”:18}
Traceback (most recent call last):
File “”, line 1, in
TypeError: unhashable type: ‘list’
dict2={“name”:“张三”,“age”:18,“name”:“李四”}
print(dict2[“name”])
李四
在python中,字典可以通过内置函数dict( )来创建字典,此时可以将列表或元组作为参数传入这个函数,如果未传入任何参数,则会生成一个空字典。
dict1=dict()
dict1
{}
传入的参数为列表,列表的元素为元组,每个元组内包含两个元素
list1=[(“name”,“zhangsan”),(“age”,19)]
dict2=dict(list1)
dict2
{‘name’: ‘zhangsan’, ‘age’: 19}
可以通过”键=值”的形式传入dict()函数,此时键必须是字符串类型而且不加引号。例如:
dict3=dict(name=“zhangsan”,age=19)
dict3
{‘name’: ‘zhangsan’, ‘age’: 19}
4.9.4.2 字典的基本操作
1.访问字典的元素
在字典中键的作用相当于索引,其语法格式如下:
字典名[键]
如果指定的键未包含在字典中,则会发生keyError错误。
score={“math”:86,“english”:93}
score[“math”]
86
score[“physics”]
Traceback (most recent call last):
File “”, line 1, in
KeyError: 'physics
如果字典中键的值本身也是字典,需要使用多个键来访问字典的元素。例如:
person = {“name”:{“first name”:“Bill”,“last name”:“Gates”}}
person[“name”][“first name”]
‘Bill’
person[“name”][“last name”]
‘Gates’
如果字典中键的值是列表或元组,则需要使用键和索引来访问字典元素,例如:
student={“name”:“zhangsan”,“score”:[89,76]}
student[“name”]
‘zhangsan’
student[“score”][0]
89
student[“score”][1]
76
student={“name”:“zhangsan”,(“math”,“phy”):(93,86)}
student[“name”]
‘zhangsan’
student[“math”,“phy”]
(93, 86)
student[(“math”,“phy”)]
(93, 86)
student[“math”,“phy”][0]
93
student[“math”,“phy”][1]
86
2.添加和更新字典元素
添加和更新字典元素可以通过赋值语句来实现,语法格式如下:
字典名[键]=值
如果键存在,则更新键对应的值
如果键不存在,则增加键和值
student={}
student[“name”]=“zhangsan”
student[“age”]=18
student[“score”]=[82,79,83,90]
student
{‘name’: ‘zhangsan’, ‘age’: 18, ‘score’: [82, 79, 83, 90]}
student[“name”]=“lisi”
student
{‘name’: ‘lisi’, ‘age’: 18, ‘score’: [82, 79, 83, 90]}
student[“height”]=185.5
student
{‘name’: ‘lisi’, ‘age’: 18, ‘score’: [82, 79, 83, 90], ‘height’: 185.5}
3.删除字典元素和字典
使用del语句删除一个变量,以解除该变量对数据对象的引用。若要从字典中删除指定键对应的值或删除整个字典,也可以使用del语句来实现。例如:
dict1={1:“A”,2:“B”,3:“C”}
del dict1[3]
dict1
{1: ‘A’, 2: ‘B’}
del dict1
dict1
Traceback (most recent call last):
File “”, line 1, in
NameError: name ‘dict1’ is not defined
4.检查键是否存在于字典中
每个键及其对应的值就是字典中的一个元素,可以使用in运算符检测键是否存在于字典中。例如:
dict1={1:“A”,2:“B”,3:“C”}
1 in dict1
True
4 in dict1
False
5.获取键列表和字典长度
将一个字典作为参数传入list()函数可以获取该字典中所有键组成的列表。例如:
student={“name”:“zhangsan”,“age”:19}
list(student)
[‘name’, ‘age’]
使用内置函数len()获取字典的长度,即字典中包含的元素个数。例如:
student={“name”:“zhangsan”,“age”:19}
len(student)
2
例1:
创建一个简单的学生信息录入系统,用于输入学生的姓名、性别和年龄信息。
键盘输入Y(继续)/N(退出)来让用户决定是否继续录入。
students = [] # 存放所有录入的学生信息
print(“学生信息录入系统”)
print(“-” * 60)
while True:
student = {} # 存放一个学生信息
student[“name”] = input(“请输入姓名:”)
student[“gender”] = input(“请输入性别:”)
student[“age”] = int(input(“请输入年龄:”))
students.append(student) # 将学生信息存放在列表students里面
choice = input(“是否继续录入学生信息(Y/N):”)
if choice.upper() == “N”:
break
print(“-” * 60)
print(f"本次一共录入{len(students)}个学生")
i = 1
for stu in students:
print(“学生{}:{}”.format(i, stu))
i += 1
4.9.4.3 字典的常用方法
1.dict.keys( ) 用于获取dict中所有键的列表。例如:

2.dict.values() 用于获取dict中所有值的列表。例如:

3.dict.items() 用于获取dict中所有的(键,值)元组的列表。例如:

4.dict.get(key[,value]) 用于从dict中获取键为key对应的值,如果dict中存在key就会返回key对应的值,如果不存在key,则会返回None,如果给定了value,就会返回给的value值,例如:

dict1={“name”:“zhangsan”,“age”:18}
dict1.get(“age”)
18
dict1.get(“gender”)

dict1.get(“gender”,19)
19

5.dict.copy() 用于获取dict的一个副本,例如:

dict1={“name”:“zhangsan”,“age”:18}
dict2 = dict1.copy()
dict2
{‘name’: ‘zhangsan’, ‘age’: 18}

6.dict.clear()用于删除字典dict中的所有元素,使dict变成一个空字典。

dict1={“name”:“zhangsan”,“age”:18}
dict1.clear()
dict1
{}
7.dict.pop(key[,value]) 用于从dict中删除键key和其对应的值并返回相应的值,如果健key在字典dict中不存在,则返回value的值(默认返回None),例如:
dict1={“name”:“zhangsan”,“age”:18}
dict1.pop(“age”)
18
dict1
{‘name’: ‘zhangsan’}
dict1={“name”:“zhangsan”,“age”:18}
dict1.pop()
Traceback (most recent call last):
File “”, line 1, in
TypeError: pop expected at least 1 argument, got 0
dict1={“name”:“zhangsan”,“age”:18}
dict1.pop(“gender”,19)
19
8.dict.setdefault(key[,value]).如果字典dict中存在key,则该方法返回key对应的值,否则在字典dic中添加key:value,并返回value的值,value默认为None.
dict1={“name”:“zhangsan”,“age”:18}
dict1.setdefault(“age”,“haha”)
18
dict1.setdefault(“gender”,“haha”)
‘haha’
dict1
{‘name’: ‘zhangsan’, ‘age’: 18, ‘gender’: ‘haha’}

9.dict.update(dict2) 用于将字典dict2中的元素添加到字典dict中,例如:

dict1={“name”:“zhangsan”}
dict2={“age”:18}
dict1.update(dict2)
dict1
{‘name’: ‘zhangsan’, ‘age’: 18}

10.dict.popitem() 用于从字典dict中删除一个元素,并返回一个由键和值构成的元组,例如:

dict1={“name”:“zhangsan”,“age”:18}
dict1.popitem()
(‘age’, 18)

11.dict.fromkeys(seq,[value])用于创建一个字典,并使用序列中的元素作为键,使用指定的值作为所有键对应的初始值,(默认None).例如:

{}.fromkeys((“name”,“gender”,“age”),“”)
{‘name’: ‘’, ‘gender’: ‘’, ‘age’: ‘’}
{}.fromkeys((“name”,“gender”,“age”),(“zhangsan”,“man”,18))
{‘name’: (‘zhangsan’, ‘man’, 18), ‘gender’: (‘zhangsan’, ‘man’, 18), ‘age’: (‘zhangsan’, ‘man’, 18)}

例1:
创建一个简单的学生信息录入系统,用于输入学生的姓名、性别和年龄信息并以字符串形式输出学生信息。
students = []
print(“学生信息录入系统:”)
print(“-” * 60)
while True:
student = {}
student[“姓名”] = input(“请输入姓名:”)
student[“性别”] = input(“请输入性别:”)
student[“年龄”] = int(input(“请输入年龄:”))
students.append(student)
choice = input(“是否继续输入(Y/N):”)
if choice.upper() == “N”:
break
print(“-” * 60)
print(“录入的学生信息如下:”)
for dic in students[0]: # students[0]是随便选择一个来遍历键
print(dic, end=“\t”)
print() # 换行
for i in students:
for j in i.values():
print(j, end=“\t”)
print() # 换行
章节测试题

5.函数与模块
函数分为系统函数和用户自定义函数,系统函数包括Python内置函数,标准模块中的函数以及各种对象的成员方法等。用户自定义函数则是用户根据需要自己编写的函数。而模块是更高级别的程序组织单元,模块分为系统模块和用户自定义模块,用户自定义模块就是一个扩展名为”py”的程序文件,在一个模块中可以包含多个函数,在编写实践中,可以将经常用到的程序代码定义成函数放在不同的模块文件中,在需要时可以导入模块调用其中的各个函数,以提高代码的重复利用率。
5.1函数的定义
函数由def关键字、函数名、函数参数、函数体、函数返回值组成。其中的函数参数和函数返回值是可选项,根据需要是否添加。
def 函数名([形式参数1, 形式参数2…]):
函数体
[返回值]
定义函数时以def关键字开头,后接函数名、圆括号和冒号1;圆括号内可以用于定义形式参数(简称形参),形参是可选的,形参必须放在圆括号内,不同形参之间用逗号分隔。函数体向右缩进,第一行可以选择性地使用文档字符串,用于存放函数说明,文档字符串通常使用三引号注释来多行字符串;在函数体中可以使用return [表达式]来结束函数,返回你指定的结果。如果未使用return语句,或者使用了不带表达式的return语句,系统则返回None。
例1:
定义一个用于计算矩形面积的函数area,并在Python命令行终端中查看该函数的帮助文档。
def area(width, height):
“”"
:param width: 宽
:param height: 高
:return: 矩形的面积
“”"
return width * height
5.2函数的调用
调用函数时,直接在语句中输入函数名并在后面的圆括号内传入实际参数(简称实参),多个参数之间用逗号分隔,其语法格式如下:
函数名(实际参数列表)
此时提供的实际参数应当与定义该函数时指定的形式参数按顺序一一对应,而且参数的数据类型要保持兼容。
调用无参数函数时,可以使用以下语法格式:
函数名( )
此时函数名后面的圆括号不能省略。
如果函数没有返回值,则可以在语句中直接调用函数。
如果函数有返回值,则可以在调用函数后将返回值传递出来,此时可以将函数调用作为一个值用在表达式中,或者作为参数传入其他函数中。对于有返回值的函数,如果也将其作为语句来使用,那么系统会忽略函数的返回值。
函数定义和函数调用可以放在同一个程序文件中,此时函数定义必须位于函数调用之前。函数定义和函数调用也可以放在不同的程序文件中,此时需要首先导入函数定义所在的模块,然后才能调用函数。
在一个程序文件中可以定义多个函数,通常需要定义一个main()函数作为程序的主函数,也就是程序的入口,并在主函数中调用其他函数,以完成程序的总体调度功能。
例1:
从键盘输入三角形的底和高,计算输出三角形的面积。

定义函数

def area(base, height):
return base * height / 2 # 返回面积
def main():
x = float(input(“请输入三角形的底边长:”))
y = float(input(“请输入三角形的高:”))
print(“三角形的面积为:”, area(x, y))

调用主函数

main()
5.3函数参数的传递
如果定义函数时指定了形参,则调用函数时必须传入相应的实参,通过形参和实参的结合在函数和函数之间传递数据。
5.3.1函数参数的传递方式
定义函数时所指定的形参并不是具有值的变量,它所起的作用类似于占位符,只有在调用函数时,调用函数将实参的值传递给被调用函数的形参,形参才具有确定的值。要正确地传递参数,一般要求形参和实参数目要相等,而且数据类型要保持兼容。
首先我们来看一个示例:
示例1:
def test(num):
num += 1
return num
a = 1
print(test(a))
示例2:
def test01(list):
list.append(“hello”)
return list
list1 = [1, 2, 3]
print(test01(list1))
print(list1)
在python中,如果参数属于可变对象,则在函数内部对形参变量的修改会影响到函数外部的实参边变量,这相当于引用传递方式;如果参数属于不可变对象,则在函数内部对形参变量的修改将不会影响到函数外部的实参变量,这相当于值传递方式。
接下来我们探讨一下什么是引用值传递方式和传递方式?
1)值传递方式 对被调用函数的形参变量重新分配存储空间,用于存放传递过来的实参变量的值,从而形成实参变量的副本。被调用函数中对形参变量的任何操作仅限于该函数内部,而不会对调用函数中的实参变量产生影响。
2)引用传递方式 对被调用函数的形参变量分配存储空间,用于存储由调用函数传递过来的实参变量的地址。被调用函数中对形参变量的任何操作将会对调用函数中的实参变量产生影响。
例1:
向函数中传入不同数据类型的参数,查看修改形参是否影响是否影响实参的值。

def change(num,string,lst,tup,set,frzset,dic):
num+=100
# print(num1)
string = string.upper()
# print(string)
lst.sort()
# print(lst)
tup = (4,5,6)
# print(tup)
set.add(“python”)
# print(set)
frzset |= {4,5,6}
# print(frzset)
dic[2] = “python”
# print(dic)

name__表示当前模块名 当模块被直接运行时模块名为__main

if name == ‘main’:
num1=123
str1 = “python”
list1=[3,1,2,5]
tup1=(1,2,3)
set1={1,2,3}
frset1 = frozenset([1,2,3])
dict1={1:“hello”,2:“world”}
print(num1)
print(str1)
print(list1)
print(tup1)
print(set1)
print(frset1)
print(dict1)
print(“*” * 50)
# 调用函数
change(num1,str1,list1,tup1,set1,frset1,dict1)
print(num1)
print(str1)
print(list1)
print(tup1)
print(set1)
print(frset1)
print(dict1)
总结:
可变数据类型:列表、字典、可变集合
不可变数据类型:数值、字符串、元组、不可变集合
5.3.2函数参数类型
在python中,调用函数可以传入的参数类型有:位置参数、关键字参数、默认值参数、不定长参数(元组类型和字典类型的不定长参数)、函数对象参数等。
1.位置参数
调用函数时,通常按照从左到右的顺序将各个实参依次传递给相应的形参,此时要求实参的数目与形参的数目相等。如果实参的数目与形参的数目不相等,则会出现TyprError错误。例如:

def add(x,y):
… return x+y

add(1,2)
3
add(1,2,3)
Traceback (most recent call last):
File “”, line 1, in
TypeError: add() takes 2 positional arguments but 3 were given

2.关键字参数
调用函数时,如果不想按照位置匹配的方式传递参数,则可以使用传递关键字参数,即通过形参的名称来指定将实参值传递给哪个形参。传递关键字参数的语法格式如下:
形参名称=实参值
请看下面的示例:
def test(name, age):
print(f"my name is {name} and my age is {age}.")
test(“张三”, 18) # 按照位置匹配的方式调用
test(age=18, name=“张三”) # 按照关键字参数的方式调用
3.默认值参数
定义函数时可以为形参指定默认值,调用带有默认值参数的函数时,如果未提供参数值,则形参会取默认值。语法格式如下:
形参名称=默认值
需要注意的是:默认值参数必须位于形参列表的最右端,如果对一个形参设置了默认值,则必须对其右边的所有形参设置默认值,否则会出现错误!(出现的错误如下图)

示例代码:
def test(name=“张三”, age=18):
print(f"my name is {name} and my age is {age}.")
test(“李四”, 19) # 调用函数时,给函数传参
test() # 调用函数时,不传参,被调函数使用默认参数
4.不定长参数(args,**kwargs)
定义函数时,如果参数的数目不固定。则可以使用不定长参数。方法就是在形参名称前面加星号“
”会将参数封装成元组,在形参名称前面加星号“**”会将参数封装成字典。注意:不定长参数一定要放在其他的形参后面。
def hobbys(name,age,*hobby,info):
print(f"my name is {name} and my age is {age}")
if hobby:
print(hobby)
if info:
print(info)
hobbys(“张三”,18,“跑步”,“蹦极”,“画画”,weiht=75,height=178)
上面的“
”会将参数封装成字典,在调用函数的时候,传参的方式为:
键=值
将键和值组成一个元素添加到字典中,如果未提供任何实参,则相当于提供一个空字典作为参数.
5.3.3两类特殊函数
1) 匿名函数
什么是匿名函数:匿名函数是指没有名称的函数,它只能包含一个表达式,而不能包含其他语句,该表达式的值就是函数的返回值。
什么时候使用匿名函数:如果某项计算功能只需要临时使用一次而不需要在其他地方重复使用,则可以考虑通过定义匿名函数来实现这项功能。
1.匿名函数的定义
匿名函数通过关键字lambda来定义,因此也称为lambda函数其语法格式如下:
lambda 参数列表:表达式
参数列表中的参数之间用逗号分隔,冒号后面的表达式用于确定匿名函数的返回值,表达式的值就是匿名函数的返回值。
2.匿名函数的调用
在程序中可以将匿名函数赋值给一个变量,然后通过该变量来调用匿名函数。例如:

f=lambda x,y :x+y
f(3,5)
8
f=lambda x,y :xy
f(3,5)
15
与标准函数类似,使用匿名函数时可以使用默认值参数和关键字参数,例如:
f=lambda a,b=6,c=3:b**2-4
a*c
f(2) # 后面两个参数使用默认值
12
f(3,20) # 第三个参数使用默认值
364
f(5,9,1)
61
f(c=2,a=3,b=10) # 使用关键字参数
76
3.匿名函数作为序列或字典的元素
在列表、元组或字典中,也可以将匿名函数作为元素来使用。在这种情况下,可以通过引用列表、元组或字典元素来调用匿名函数。例如:

运用在字典中

op1 = {“add”: lambda x, y: x + y, “sub”: lambda x, y: x - y, “mult”: lambda x, y: x * y, “div”: lambda x, y: x / y}
print(op1[“add”](2, 3))
print(op1[“sub”](4, 3))
print(op1[“mult”](2, 3))
print(op1[“div”](2, 4))
print(“*”*50)

运用在列表中

op2 = [lambda x, y: x + y, lambda x, y: x - y, lambda x, y: x * y, lambda x, y: x / y]
print(op2[0](2, 3))
print(op2[1](4, 3))
print(op2[2](2, 3))
print(op2[3](2, 4))
print(“*”*50)

运用在元组中

op3 =(lambda x, y: x + y, lambda x, y: x - y, lambda x, y: x * y, lambda x, y: x / y)
print(op3[0](2, 3))
print(op3[1](4, 3))
print(op3[2](2, 3))
print(op3[3](2, 4))
4.匿名函数作为函数的返回值
在函数中,可以在return语句中使用匿名函数,以匿名函数作为函数的返回值。
请看下面的示例:
使用匿名函数实现算术的四则运算
def arithmetic©:
if c == “+”:
return lambda x, y: x + y
if c == “-”:
return lambda x, y: x - y
if c == “":
return lambda x, y: x * y
if c == “/”:
return lambda x, y: x / y
if name == ‘main’:
x, y = eval(input(“请输入两个数字:”))
choice = input("请选择一种运算方式(±
/):”)
if choice in [“+”, “-”, “*”, “/”]:
print(f"{x}{choice}{y}={arithmetic(choice)(x,y)}")
2) 递归函数
如果一个函数在内部直接或间接地调用该函数本身,则这个函数就是递归函数。
递归函数的特点:必须有一个明确的递归结束条件,每当进入更深一层递归时,问题规模相比上次递归都应有所减少;相比两次重复之间有紧密的联系,前一次要为后一次做准备,通常前一次的输出会作为后一次的输入。
我们先来看看简单的示例:
斐波那契数列:
1,1,2,3,5,8,13,21,…
用函数表达出斐波拉锲的通项公式:
def Fibonacci(n):
if n <= 2:
return 1
else:
return Fibonacci(n - 1) + Fibonacci(n - 2)

列出前10项的斐波拉锲的数列

for i in range(1, 11):
print(i, end=“\t”)

def fact(n):
if n <= 1:
return 1
else:
return n * fact(n - 1)

print(fact(5))
5.3.4变量的作用域
程序中能够对变量进行存取操作的范围称为变量的作用域,变量按照作用域的不同一般分为局部变量和全局变量。函数内部定义的局部变量只能在函数内部使用;嵌套函数中外层函数定义的局部变量在外层函数和内层函数中能够使用;如果外层函数引用内层函数对象的方法作为其返回值,则内层函数称为闭包,全局变量是在一个模块中所有函数之外定义的变量,可以在多个函数中使用。
1)局部变量
在一个函数体或语句块内部定义的变量称为局部变量。局部变量的作用域就是定义它的函数体或语句块,只能在这个作用域内部对局部变量进行存取操作,而不能在这个作用域外部对局部变量进行存取操作。对于带参数的函数而言,其形参的作用域就是函数体。
如果在函数外部引用函数的形参或函数体中定义的局部变量,则会出现NameError的错误,例如:

def test(x,y):
… a = x+y
… b = x-y
… print(a,b)

test(20,10)
30 10
a
Traceback (most recent call last):
File “”, line 1, in
NameError: name ‘a’ is not defined
x
Traceback (most recent call last):
File “”, line 1, in
NameError: name ‘x’ is not defined
在具有嵌套关系的函数中,在外层函数中定义的局部变量可以直接在内层函数中使用,默认情况下,不属于当前局部作用域的变量具有只读的性质,可以直接对其进行读取,如果对其赋值,只能在内部函数使用。但不会修改外层函数的变量。
def outer():
x = 3
y = 4
z = 5

def inner():
    x = 8
    print(x + y + z)

inner()
print(x)

outer()
如果想要修改外层函数中的变量的值,需要使用关键字nonlocal对变量进行声明。
def outer():
x = 3
y = 4
z = 5

def inner():
    nonlocal x
    x = 8
    print(x + y + z)

inner()
print(x)

outer()
1)全局变量
在所有函数外部定义的变量称为全局变量,它可以在当前模块范围中被所有函数引用。如果要在函数内部修改全局变量的值,则应使用global关键字对变量声明。
在python程序中引用变量的优先级顺序:当前作用域局部变量>外层作用域变量>当前模块中的全局变量>Python内置变量
正因为全局变量可以多个函数中使用,在一个函数中更改了全局变量的值就可能会对其他函数的执行产生影响,所以在程序中不宜过多使用全局变量。
5.3.5模块的定义和使用
Python中,模块分为标准模块和用户自定义模块
标准模块是由python提供的函数模块,也称为标准库。Python提供丰富的标准模块,可以用于数学运算、字符串处理、文件操作、通用操作系统服务、网络和Internet编程、图形绘制、多媒体服务、图形用户界面构建以及数据库访问等。
用户自定义模块就是用户自己编写的Python程序文件,创建一个模块并在其中定义某些函数和变量后,在其他需要这些功能的文件中导入这个模块并调用期中的函数。
1.导入整个模块
import 模块名1[as 别名][,模块2 [as 别名2][,…,模块名n [as 别名n]]]
其中模块名就是去掉拓展名”.py”后的文件名,导入多个模块时,各个模块名之间需要用逗号分隔。导入模块时还可以给模块指定别名。一般用于如果模块名较长,可以指定简短的别名。
如果指定的模块不存在,或该模块未包含在Python搜索路径中,则执行import语句时将会引发ModuleNotFoundError的错误。
导入模块后,就可以调用该模块里面的所有函数,调用语法格式如下:
模块名或别名.函数名(参数)
TODO此处暂未完善后续更新…
6.面向对象编程
面向对象编程是一种计算机程序设计架构,基本原则是计算机程序是由单个能够起到子程序作用的对象组合而成。为了实现预期的功能,每个对象都能够接收信息、处理数据和向其他对象发送信息。Python 从设计之初就是一种面向对象的程序设计语言,在 Python 中通过创建类和对象来开发应用程序是很方便的。
本章讨论如何使用 Python 进行面向对象的程序设计,主要内容包括面向对象编程概述、类与对象、成员属性、成员方法以及类的继承等。9
6.1 面向对象编程概述
面向对象编程是目前比较流行的程序设计方法。在面向对象程序设计中,数据和对数据的操作可以封装在一个独立的数据结构中,这个数据结构就是对象,对象之间通过消息的传递来进行相互作用。由于面向对象本身固有的特性,使得面向对象编程已经达到软件工程的三个主要目标,即重用性、灵活性和可扩展性。
6.1.1 面向对象的基本概念
使用 Python 进行面向对象编程,需要先了解以下基本概念:
1.对象
对象是人们要进行研究的任何事物,从最简单的整数到复杂的航天飞机等都可以看成对对象。对象不仅能表示具体的事物,还能表示抽象的规则、计划或事件。对象的状态和特征用数据值表示出来就是属性;对象的操作用于改变对象的状态,这些操作通过程序代码来实现的话就是方法。对象实现了数据和操作的结合,数据和操作封装于对象这个统一体中。
2.类
类是对象的模板,是对一组具有相同属性和相同操作的对象的抽象。类实际上就是一种数据类型,一个类所包含的数据和方法用于描述一组对象的共同属性和行为。类的属性是对象状态的抽象,可以用数据结构来描述;类的操作是对象行为的抽象,可以用操作名和实现该操作的方法来描述。属性和方法统称为类的成员。类是对象的抽象化,类是在对象之上的抽象,对象则是类的具体化,是类的实例,从一个类可以创建多个对象。
3.消息
一个程序中通常包含多个对象,不同对象之间通过消息相互联系、相互作用。消息由某个对象发出,用于请求另一个对象执行某项操作,或者回复某些信息。在对象的操作中,当发送者将一个消息发送给某个对象时,消息包含接收对象去执行某种操作的信息。发送一条消息至少要说明接受消息的对象名、发送给该对象的消息名(即对象名和方法名)。一般还要对参数加以说明,参数可以是认识该消息的对象所知道的变量名,或者是所有对象都知道的全局变量名。
4.封装
封装是指将对象的数据(属性)和操作数据的过程(方法)结合起来所构成的单元,其内部信息对外界是隐藏的,外界不能直接访问对象的属性,而只能通过类对外部提供的接口对该对象进行各种操作,这样可以保证程序中数据的安全性。类是实施数据封装的工具,对象则是封装的具体实现,是封装的基本单位。定义类时将其成员划分为公有成员、私有成员和保护成员,从而形成了类的访问机制,使得外界不能随意存取对象的内部数据(即成员属性和成员方法)。
5.继承
继承是指在一个类的基础上定义一个新的类,原有的类称为基类、超类或父类,新生成的类称为派生类或子类。子类不仅可以通过继承从父类中得到所有的属性和方法,也可以对所得到的这些方法进行重写和覆盖,还可以添加一些新的属性和方法,从而扩展父类的功能。
从一个父类可以派生出多个子类,每个子类都可以通过继承和重写拥有自己的属性和方法,父类体现出对象的共性和普遍性,子类则体现出对象的个性和特殊性,父类的抽象程度高于子类。继承具有传递性,从子类也可以派生出新一代孙类,相对于孙类而言,子类又成了父类。继承反映了抽象程度不同的类之间的关系,即共性和个性的关系,普遍性和特殊性的关系。编程人员可以在原有类的基础上定义和实现新类,从而实现了程序代码的重用性。
6.多态
多态是指一个名称相同的方法产生了不同的动作行为,即不同对象收到相同的消息时产生了不同的行为方式。多态允许将父对象赋值成为其子对象,赋值之后父对象可以根据当前赋值给它的子对象的特性以不同的方式运作。多态可以通过覆盖和重载两种方式来实现,覆盖是指在子类中重新定义父类的成员方法,重载则是指允许存在多个同名函数,而这些函数的参数列表有所不同。
6.1.2 面向过程与面向对象的比较
在程序设计领域,存在着两种不同的程序设计方式,即面向过程编程和面向对象编程。面向过程编程就是通过算法分析列出解决问题所需要的操作步骤,将程序划分为若干个功能模块,然后通过函数来实现这些功能模块,在解决问题的过程中根据需要调用相关的函数。
面向对象编程则是将构成问题的事务分解成各个对象,根据对象的属性和操作抽象出类的定义并基于类创建对象,其目的并不是为了完成一个步骤,而是为了描述某个事物在整个解决问题的过程中的行为。面向对象编程是一种以对象为基础,以事件或消息来驱动对象执行处理的程序设计方法,面向对象编程的主要特征是具有抽象性、封装性、继承性及多态性。
面向过程编程和面向对象编程的区别主要表现在以下几个方面。
1)面向过程编程方法是通过函数(或过程)来描述对数据的操作,但又将函数与其操作的数据分离开来;面向对象编程方法是将数据和对数据的操作封装在一起,作为一个对象整体来处理。
2)面向过程编程方法是以功能为中心来设计功能模块,程序难以维护;面向对象编程方法是以数据为中心来描述系统,数据相对于功能而言具有较强的稳定性,因此程序更容易维护。
3)面向过程程序的控制流程由程序中预定顺序来决定;面向对象程序的控制流程由运行时各种事件的实际发生来触发,而不再由预定顺序来决定,因此更符合实际需要。在实际应用中,应根据具体情况来选择使用哪种程序设计方法。例如,要开发一个小型应用程序,代码量比较小,开发周期短,在这种情况下使用面向过程编程方法就是一个不错的选择,此时如果使用面向对象编程方法反而会增加代码量,降低工作效率。而要开发一个大型应用程序,使用面向对象编程方法会更好一些。
Python 同时支持面向过程编程和面向对象編程。函数就是面向过程编程的基本单元,函数是 Python 支持的一种封装,通过把大段代码拆成函数并一步一步地调用函数,就可以把一个复杂任务分解成一系列简单的任务,这是典型的面向过程编程。
面向对象编程是将对象作为程序的基本单元,一个对象包含了数据和操作数据的函数。在Python 中,所有数据类型都可以视为对象,当然也可以自定义对象,自定义的对象数据类型便是面向对象中的类的概念。在程序设计中围绕类展开,通过定义类来构建程序要完成的功能,并通过主程序和相关函数使用类创建所需的对象,体现了面向对象的编程理念。
6.2 对象与类
在 Python 中,类是一种自定义的复合数据类型,也是功能最强大的数据类型。面向对象编程的基本步骤是:首先通过定义类来设置数据类型的数据和行为,然后基于该类创建对象,并通过存取对象的属性或调用对象的方法来完成所需操作。
6.2.1 类的定义
类可以通过 class 语句来定义,其语法格式如下:
class 类名:
类体
定义一个类时,以关键字 class 开始,后跟类名和冒号。类名遵循标识符命名规则,其首字母通常采用大写形式,右缩进对齐。
在类体中定义类的所有变量成员和函数成员。变量成员即类的属性,用于描述对象的状态和特征;函数成员即类的方法,用于实现对象的行为和操作。通过定义类可以实现数据和操作的封装。类体中也可以只包含一个 pass 语句,此时将定义一个空类。
在 Python 中,一切皆对象。定义了一个类对象,就可以通过类名和圆点运算符“.”来访问类的属性,其语法格式如下:
类名.属性名
示例:类定义示例
class Student: # 定义Student类
name = “张三” # 定义类的属性
gender = “男”
age = 18

def hobby(self):
    print("喜欢游泳")

访问类的属性

print(“姓名:”, Student.name)
print(“性别:”, Student.gender)
print(“年龄:”, Student.age)
6.2.2 创建对象
类是对象的模板,对象是类的实例。定义类之后,可以通过赋值语句来创建类的实例对象,其语法格式如下:
对象名=类名(参数列表)
创建对象之后,该对象就拥有类中定义的所有属性和方法,此时可以通过对象名和圆点运算符“.”来访问这些属性和方法,其语法格式如下:
对象名.属性名
对象名.方法名(参数)
示例:利用类和对象计算圆的周长和面积
import math

class Circle:
radius = 0
def getPerimeter(self):
return 2 * math.pi * self.radius
def getArea(self):
return math.pi * self.radius ** 2

c1 = Circle() # 创建类的实例对象
c1.radius = 10 # 设置对象的属性值
print(f"当半径为{c1.radius}时:")

调用类的方法

print(f"周长={c1.getPerimeter()},面积={c1.getArea()}“)
c2 = Circle() # 再用类创建一个实例对象
c2.radius = 20 # 设置对象的属性值
print(f"当半径为{c2.radius}时:”)

调用类的方法

print(f"周长={c2.getPerimeter()},面积={c2.getArea()}")
6.3 成员属性
在类中定义的变量就是属性。属性按所属的对象可以分为类属性和实例属性,类属性是类对象所拥有的属性;实例属性是该类的实例对象所拥有的属性。
6.3.1 类属性
类属性按能否在类的外部访问可以分为公有属性和私有属性,通过在类中所有方法之外通过定义成员变量来创建,创建类之后也可以在类的外部通过类名和圆点运算符来添加公有属性。定义属性时,如果属性名以双下画线“__”开头,则该属性就是私有属性,在类中所有方法之外,无论是公有属性还是私有属性都可以直接访问,在类的成员方法内部则要通过“类名.属性名”形式来访问。在类的外部,公有属性仍然可以通过“类名.属性名”来访问,私有属性则不能通过这种形式来访问。如果试图通过“类名.属性名”来访问私有属性,系统则会发出 AttributeError 错误。
一般情况下,不允许也不提倡在类的外部访问类的私有属性。如果一定要在类的外部对类的私有属性进行访问,则需要使用一条下画线开头,后跟类名和私有属性名。
例如,如果在类 MyClass 内部定义了一个名为_attr 的私有成员属性,则在类成员方法之外可以直接通过_attr形式访问这个私有属性,在类成员方法里面通过以下形式来访问它:
self._attr
在类的外部,这个私有属性必须通过以下形式来访问:
MyClass._MyClass_attr
示例:创建一个MyClass类,访问公有和私有属性,以及类的方法。
class MyClass:
man = 18
woman = 12
man_avg_height = 175 # 以上为公有属性
__woman_avg_height = 165 # 定义私有属性

def class_info(self):  # 定义类的方法
    # 在类的方法中可以直接调用私有属性和公有属性
    print(f"班级中男生的人数:{self.man},男生的平均身高:{self.man_avg_height}")
    print(f"班级中女生的人数:{self.woman},女生的平均身高:{self.__woman_avg_height}")

c1 = MyClass() # 创建实例对象

访问类的公有属性

print(c1.man)
print(c1.woman)
print(c1.man_avg_height)

访问类的私有属性,需要使用一条下画线开头,后跟类名和私有属性名,才能访问。否则会出现 AttributeError 错误

print(c1._MyClass__woman_avg_height)
c1.class_info() # 访问类的成员方法
6.3.2 实例属性
实例属性是类的实例对象所拥有的属性,实例属性可以在类的内部或类的外部通过赋值语句来创建。
1)在类的内部,定义类的构造方法_init_或其他实例方法时,通过在赋值语句中使用self关键字、圆点运算符和属性名来创建类的属性,其语法格式如下:
self.属性名=值
其中 self 是类成员方法的第一个参数,代表类的当前实例。定义类的方法时,必须设置一个用于接受类的实例的参数,而且这个参数必须是第一个参数。在实例方法中,可以通过“self.属性名”形式来访问类的属性。
2)在类的外部,创建类的实例对象后,可以通过在赋值语句中使用实例对象名、圆点运算符和属性名来创建新的实例属性,其语法格式如下:
实例对象名.属性名=值
其中对象名表示类的一个实例。在类的外部,同样也可以通过“对象名.属性名”形式来读取已经存在的实例属性的值。也可以覆盖(修改)当前实例对象的实例属性的值。
在 Python 中,通过类来实例化一个对象之后,可以通过实例化对象的_dict_属性来检查该对象中包含哪些实例属性(其实就是实例对象新建的属性或者是修改的类的属性)也可以通过实例对象的_class_属性来检查实例对象所属的类。
示例:请看下面的示例
class MyClass:
man = 18
woman = 12
man_avg_height = 175 # 以上为公有属性
__woman_avg_height = 165 # 定义私有属性
avg_height = (man_avg_height * man + __woman_avg_height * woman) / (man + woman) # 类方法外,直接使用私有和公有属性

def class_info(self):  # 定义类的方法
    # 在类的方法中可以直接调用私有属性和公有属性
    print(f"班级中男生的人数:{self.man},男生的平均身高:{self.man_avg_height}")
    print(f"班级中女生的人数:{self.woman},女生的平均身高:{self.__woman_avg_height}")
    print(f"班级男生和女生的平均身高:{self.avg_height}")

c1 = MyClass() # 创建实例对象

访问类的公有属性

print(c1.man)
print(c1.woman)
print(c1.man_avg_height)

访问类的私有属性,需要使用一条下画线开头,后跟类名和私有属性名,才能访问。否则会出现 AttributeError 错误

print(c1._MyClass__woman_avg_height)
c1.class_info() # 访问类的成员方法
c1.man_avg_weight = 75 # 给实例对象c1创建新的属性
print(f"男生平均体重:{c1.man_avg_weight}“)
c1.woman=10 # 修改实例对象c1的属性
print(f"班级女生人数:{c1.woman}”)
print(“*”*50)
print(c1.dict) # 查看实例对象c1包含的实例属性(其实就是实例对象新建的属性或者是修改的类的属性)
print(c1.class) # 通过实例对象的_class_属性来检查对象所属的类
6.3.3 类属性与实例属性的比较
类属性与实例属性既相互区别又相互联系,搞清楚这种关系对掌握 Python 面向对象编程是很重要的。类属性与实例属性的区别表现在以下 3 个方面。
1)所属的对象不同:类属性属于类对象本身,可以由类的所有实例共享;实例属性则属于类的某个特定实例。如果存在同名的类属性和实例属性,则两者相互独立、互不影响。
2)定义的方法不同:类属性是在类中所有成员方法之外定义的,实例属性则是在构造方法或其他实例方法中定义的。
3)引用的方法不同:类属性是通过“类名.属性名”形式引用的,实例属性则是通过“对象名.属性名”形式引用的。
类属性与实例属性的共同点和联系表现在以下 2个方面。
1)类对象和实例对象都是对象,它们所属的类都可以通过_class_属性来获取.
2)类对象和实例对象包含的属性及其取值都可以通过_dict_属性来获取,该属性的取值是一个字典,每个字典元素中包含一个属性及其对应的值。
class Animal:
# 类的属性
weight = 0
heigth = 0
# 构造方法,定义实例属性
def init(self, species, breed):
# 实例属性
self.species = species
self.breed = breed
# 类的方法
def showinfo(self):
print(f"物种是{self.species},属于{self.breed}的品种。“)
print(f”{self.breed}的体重{self.weight},身高{self.heigth}")

dog1 = Animal(“犬科”, “田园犬”)
dog1.weight = 20 # 这里其实就是调用类属性,重写了类的属性值,但不会修改类的属性。只是在该实例中生效。
dog1.heigth = 50
dog2 = Animal(“犬科”, “萨摩耶”)
dog2.weight = 30
dog2.heigth = 40
dog1.showinfo()
dog2.showinfo()
6.4 成员方法
定义类时,除了定义成员属性外,还需要在类中定义一些函数,以便对类的成员属性进行操作。
6.4.1 内置方法
在 Python 中,每当定义一个类时,系统都会自动地为它添加一些默认的内置方法,这些方法不需要显式调用,它们的命名也有特殊的约定。下面介绍两
个常用的内置方法,即构造方法和析构方法。
1.构造方法
构造方法_init_(seif,…)是在创建新对象时被自动调用的,可以用来对类的实例对象进行一些初始化操作,例如设置实例属性。如果在类中未定义构造方法,则系统将执行默认的构造方法。构造方法支持重载,定义类时可以根据需要重新编写构造方法。
定义构造方法时,第一个参数为 self,这个名称只是一种习惯用法,也可以用其他名称,例如 this、me 等。self 参数用于接受类的当前实例,除了 self参数,如果构造方法包含其他参数,这些参数在创建类的新实例时必须提供,即写在类名后面的圆括号中。
示例:构造方法示例
class Car:
def init(self, brand, color):
self.brand = brand
self.color = color
def run(self):
print(“{}的{}在行驶中…”.format(self.color, self.brand))
if name == ‘main’:
car1 = Car(“宝马”, “黑色”)
car1.run()
car2 = Car(“奔驰”, “白色”)
car2.run()

2.析构方法
析构方法__del__(self)是在对象被删除之前被自动调用的,不需要在程序中显式调用,当程序运行结束时,在程序中创建的对象会被删除,此时系统会自动调用析构方法;当离开某个作用域(如函数)时,在该作用域中创建的对象会被删除,此时析构方法会被调用一次,这样可以来释放内存空间。析构方法支持重载,通常可以通过该方法执行一些释放资源的操作。
示例:析构方法示例

class Car:
def init(self, brand, color):
self.brand = brand
self.color = color
def run(self):
print(“{}的{}在行驶中…”.format(self.color, self.brand))
def del(self):
print(“用来释放资源”)
if name == ‘main’:
car1 = Car(“宝马”, “黑色”)
car1.run()
car2 = Car(“奔驰”, “白色”)
car2.run()
6.5 类的继承
继承是指在一个父类的基础上定义一个新的子类。子类通过继承从父类中得到所有的属性和方法,也可以对所得到的这些方法重写和覆盖,同时还可以添加一些新的属性和方法,从而拓展父类的功能。继承父类按父类的多少分为单继承和多继承,单继承是指子类从单个父类中继承,多继承则是指子类从多个父类中继承。
6.5.1 单继承
在python语言中,可以在单个父类的基础上来定义新的子类。这种继承关系称为单继承。单继承可以使用class语句来实现,其语法格式如下:
class 子类名(父类名):
类体
基于父类创建新的子类之后,改子类将拥有父类中的所有公有属性和所有成员方法,这些成员方法包括构造方法、析构方法等.
还可以在子类中拓展父类的功能,还可以通过两种方法来实现,一种方式是在子类中增加新的成员属性和成员方法,另一种方式是对父类已有的成员方法进行重定义,从而覆盖父类的同名方法。
在某些情况下,可能希望在子类中继续保留父类的功能。此时需要调用父类的方法。在子类中可以通过父类的父名或super()函数来调用父类的方法。
示例:单继承示例
class Person:
def init(self, name, gender, age):
self.name = name
self.gender = gender
self.age = age

def showInfo(self):
    print("姓名:", self.name)
    print("性别:", self.gender)
    print("年龄:", self.age)

class Student(Person):
def init(self, name, gender, age, sid):
super().init(name, gender, age) # 继承父类的初始化参数
self.sid = sid

def setScores(self, Python, Chinese, Math, English):
    self.Python = Python
    self.Chinese = Chinese
    self.Math = Math
    self.English = English

def showInfo(self):
    super().showInfo()  # 继承父类的成员方法
    print("学号:", self.sid)
    print("Python:", self.Python)
    print("语文:", self.Chinese)
    print("数学:", self.Math)
    print("英语:", self.English)

if name == ‘main’:
person = Person(“张三”, “男”, 18)
person.showInfo()
print(“*” * 50)
student = Student(“李四”, “男”, 19, “20220168”)
student.setScores(98, 97, 96, 95)
student.showInfo()
6.5.1 多重继承
除了单一继承外,Python 还允许子类从多个父类继承,这种继承关系称为多重继承。与单一继承类似,多重继承也可以使用 class 语句来实现,其语法格式如下:
class 子类名(父类名 1,父类名 2,…):
类体
使用多继承经常需要面临的问题是,多个父类中包含同名的类方法。对于这种情况,Python 的处置措施是:根据子类继承多个父类时这些父类的前后次序决定,即排在前面父类中的类方法会覆盖排在后面父类中的同名类方法。示例:多重继承示例。
示例:多继承演示:
class People:
def init(self):
self.name = People
def say(self):
print(“People类”,self.name)
class Animal:
def init(self):
self.name = Animal
def say(self):
print(“Animal类”,self.name)
#People中的 name 属性和 say() 会遮蔽 Animal 类中的
class Person(People, Animal):
pass

zhangsan = Person()
zhangsan.name = “张三”
zhangsan.say()

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值