第八章
什么是元组
元组是Python内置的数据结构之一,是一个不可变序列
不可变序列与可变序列
不可变序列:字符串、元组,不可变序列没有增删改操作
可变序列:字典、序列, 可变序列可以对序列执行增删改操作,对象地址不发生改变
元组的创建方式
1、使用小括号 t = (“hello”, 9, “python”)
2、使用内置函数tuple() t = tuple((“ccc”, 98, “aaa”))
3、只包含一个元组的元素需要使用逗号和小括号 t = (10, )
为什么要将元组设计成不可变序列:在多任务环境下,同时操作对象时不需要加锁
注意事项:
元组中存储的是对象的引用
a)如果元组中对象本身是不可变对象,则不能再引用其他对象

b)如果元组中对象本身是可变对象,则可变对象的引用不允许改变,但数据可以改变
元组的遍历
元组是可迭代对象,所以可以使用for…in进行遍历
t =(10, 20,“lll”)
for item in t:
print(item)
什么是集合
集合是Python语言提供的内置数据结构,与列表、字典一样都属于可变类型的序列,集合是没有value的字典。
集合的创建
1、直接{ } s ={“python”, 98, “hello”}
2、使用内置函数set()
集合的增、删、改、查操作
集合元素的判断操作:in或not in
集合元素的新增操作:调用add()方法,一次添加一个元素 调用updata()方法至少添加一个元素
集合元素的删除操作:调用remove()方法,一次删除一个指定元素,如果指定的元素不存在抛出KeyError
调用discard()方法,一次删除一个指定元素,如果指定的元素不存在不抛异常
调用pop()方法,一次只删除一个任意元素,不能添加参数
调用clear()方法,清空集合
两个集合之间的关系
1、两个集合是否相等,可以使用运算符==或!=进行判断
2、一个集合是另一个集合的子集,可以调用方法issubset进行判断
3、一个集合是另一个集合的超集,可以调用方法issuperset
4、两个集合是否没有交集,可以调用方法isidisjoint进行判断
集合的数学操作:交集、并集、差集、对称差集
# 集合的数学操作
s1 = {10, 20, 30, 40, 50, 60}
s2 = {10, 20, 30, 40, 90, 100, 80}
"""
两个集合的交集,可以调用intersection()方法和&
"""
print(s1.intersection(s2))
print(s1 & s2)
"""
两个集合的并集,可以调用union()方法和 |
"""
print(s1.union(s2))
print(s1 | s2)
"""
两个集合的差集,差集为所在集合减去交集的部分,可以调用difference()方法和-
"""
print(s1.difference(s2))
print(s1-s2)
"""两个集合的对称差集,可以调用symmetric_difference()方法和^"""
print(s1.symmetric_difference(s2))
print(s1 ^ s2)
集合生成式
用于生成集合的公式
{i*i for i in range(1,10)}
i*i:表示集合的表达式 i:自定义变量 range():可迭代对象
注意:没有元组生成式
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Z9xwxHBq-1616079347876)(D:\Program Files\学习笔记\python学习笔记\截图\列表、字典、元组、集合.PNG)]
第九章
字符串的驻留机制
字符串:在python中字符串是基本数据类型,是一个不可变的字符序列
什么叫字符串驻留机制?
仅保存一份相同且相同且不可变字符串的方法,不同的值被存放在字符串的驻留池中,Python的驻留机制对相同字符产只保留一份拷贝,后续创建相同字符串时,不会开辟新空间,而是把该字符串的地址赋值给新创建的变量
驻留机制的几种情况(交互式)
1、字符串的长度为0或1时
2、符合标识符的字符串
3、字符串只在编译时进行驻留,而非运行时
4、[-5,256]之间的整数数字
sys中的intern方法强制2个字符串指向同一个对象,pycharm对字符串进行了优化处理
字符串驻留机制的优缺点
1、当需要值相同的字符串时,可以直接从字符串池里拿来使用,避免频繁的创建和销毁,提升效率和节约内存,因此拼接字符串和修改字符串是比较影响性能的
2、在需要进行字符串拼接时建议使用str类型的join方法,而非+,因为join()方法是先计算出所有字符串中的长度,然后再拷贝,只new一次对象,效率要比“+”效率高
字符串的常用操作
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wWiUPnhY-1616079347878)(D:\Program Files\学习笔记\python学习笔记\截图\字符串的查询操作.PNG)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ejGG0U4R-1616079347879)(D:\Program Files\学习笔记\python学习笔记\截图\字符串的大小写转换.PNG)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-T4bl0x8i-1616079347882)(D:\Program Files\学习笔记\python学习笔记\截图\字符串内容的对齐操作.PNG)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lzV9KUnt-1616079347883)(D:\Program Files\学习笔记\python学习笔记\截图\字符串的劈分操作.PNG)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ixpNcsSt-1616079347884)(D:\Program Files\学习笔记\python学习笔记\截图\判断字符串操作的方法.PNG)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vhCjsgCw-1616079347885)(D:\Program Files\学习笔记\python学习笔记\截图\字符串操作的其他方法.PNG)]
字符串的比较
运算符:>,>=,<,<=,==,!=
比较规则:首先比较两个字符串中的第一个字符,如果相等则继续比较下一个字符,依次比较下去,知道两个字符串中的字符不相等时,其比较结果就是两个字符串的比较结果,两个字符串中的所有后续字符将不再被比较
比较原理:两个字符进行比较时,比较的是其ordinal value(原始值),调用内置函数ord可以得到指定字符的ordinal value。与内置函数ord对应的是内置函数char,调用内置函数char时指定ordinal value,可以得到其对应的字符
print("apple" > "app") # True
print("apple" > "banana") # False,相当于97<98
# 当然可以使用内置函数可以得到字符的原始值
print(ord("a"), ord("b")) # 97 98
# 也可以使用与ord对应的内置函数char,将对应的值得到对应的字符
print(chr(97), chr(98)) # a b
"""== 与 is
==比较的是value值,is比较的是两个对象的地址值
"""
a = b = "python"
c = "python"
print(a is b) #True
print(a is c) #True
print(b is c) #True
print(id(a), id(b), id(c))
字符串的切片操作
字符串是不可变序列,不具备增、删、改等操作,而且切片操作会产生新的对象
print("------------切片[start:end:step]--------------------------")
# 对s从1开始到5结束,步长为1进行切片
print(s[1:5:1])
# 对s从0开始到字符串最后结束,步长为2进行切片
print(s[::2])
# 默认从字符串的最后一个元素开始,到字符串的第一个元素结束,因为不成为负数
print(s[::-1])
# 从索引为-6开始,到字符串的最后一个元素结束,步长为1
print(s[-6::1])
格式化字符串
格式化字符串的两种方式
1、%作占位符 %s:字符串 %i或%d:整数 %f:浮点数
name = "shangsan"
age = 20
# 字符串格式化的第一种方式,使用占位符%,其中 单独的%是固定的格式
print("我叫%s,今年%d" % (name, age))
# 字符串格式化的第二种方式 ,使用{},花括号中指定的是索引,并且还使用到format函数
print("我叫{0},今年{1}岁".format(name, age))
# 字符串格式化的第三种方式,使用f-string
print(f"我叫{name},今年{age}岁")
print("%10d" % 99)
print("hellohello")
# .3表示小数点后三位
print("%.3f" % 3.1415)
# 同时表示宽度和精度
print("%10.3f" % 3.14159)
2、使用{}
print("{0}".format(3.14159))
# .3表示的是一共是3位数
print("{0:.3}".format(3.14159))
# .3f表示的是3位小数
print("{0:.3f}".format(3.14159))
# 同时设置宽度和精度,宽度是10,3位小数
print("{0:10.3f}".format(3.14159))
字符串的编码转换
为什么需要字符串的编码转换?
将字符以unicode表示通过bytes转换为二进制数据,再解码显示再计算机上
编码与解码的方式
·编码:将字符串转换为二进制数据(bytes)
·解码:将bytes类型的数据转换为字符串类型
s = "天涯共此时"
# 在GBK这种编码格式中,一个中文占两个字节
print(s.encode(encoding="GBK"))
# 在UTF-8这种编码格式中,一个中文占3个字节
print(s.encode(encoding="UTF-8"))
print("------下面是解码-------")
byte = s.encode(encoding="GBK")
# 解码需要用到byte的decode方法,并且是以什么方式编的码就要以什么方式解码
print(byte.decode(encoding="GBK"))
byte = s.encode(encoding="UTF-8")
print(byte.decode(encoding="UTF-8"))
第十章
函数的创建和调用
什么是函数?
函数就是执行特定任务和完成特定功能的一段代码
为什么需要函数?
1、复用代码
2、隐藏实现细节
3、提高可维护性
4、提高可读性便于调试
函数的创建 :
def 函数名 ([输入参数]):
函数体
[return xxx]
def calc(a, b):
c = a +b
return c
result = calc(10, 20)
print(result)
函数的参数传递
函数调用的参数传递
1、位置实参:根据形参对应的位置进行实参传递
2、关键字实参:根据形参名称进行参数传递
res = calc(b=10, a=20)
print(res)
=号左侧变量的名称称为关键字参数,传递时就不会以对应的位置进行传递,而是通过关键字
def fun(args1, args2):
print("args1", args1)
print("args2", args2)
args1 = 100
args2.append(10)
print(args1)
print(args2)
n1 = 10
n2 = [11, 22, 33]
print("n1", n1)
print("n2", n2)
# 位置传参,args1,args2是形式参数,n1,n2是实际参数,可以发现,实际参数和形式参数的名称可以不一致
fun(n1, n2)
print("n1", n1)
print("n2", n2)
"""
在函数的调用过程中,进行参数的传递,如果是不可变对象,在函数
体内的修改不会影响实参的值,其中字符串是不可变对象,而列表是可变序列,所以添加会
影响原始的值,故最后打印出来的是[11,22,33,10]
"""
函数的返回值
函数返回多个值时,结果为元组
print(bool(0))
print(bool(1))
# 可以知道0的布尔值为False
# 非0的布尔值为True
def fun(num):
# 声明一个odd列表,用于存储奇数
odd = []
# 声明一个even列表,用于存储偶数
even = []
for i in num:
if i%2:
odd.append(i)
else:
even.append(i)
return odd, even
# 函数的调用
list = [10, 29, 34, 23, 44, 53, 55]
print(fun(list))
"""函数的返回值
1、如果函数没有返回值【函数执行完毕之后,不需要给调用处提供数据】 return可以省略不写
2、函数的返回值,如果是1个 ,函数返回原类型
3、函数的返回值,如果是多个,返回的结果为元组
"""
def fun1():
print("hello")
fun1()
def fun2():
return "hello"
res = fun2()
print(res)
def fun3():
return "hello", "world"
print(fun3())
"""函数在定义时,是否需要返回值视情况而定
"""
函数的参数定义
函数定义默认值参数
函数定义时,给形参设置默认值,只有与默认值不符的时候才需要传递实参
# b就称为默认值参数
def fun(a, b=10):
print(a, b)
# 函数调用
fun(100)
fun(20, 30)
个数可变的位置参数
定义函数时,可能无法事先确定传递为的位置实参的个数时,使用可变的位置参数,使用*定义个数可变的位置形参,结果为一个元组
个数可变的关键字形参
定义函数时,无法事先确定传递的关键字实参的个数时,可以使用可变的关键字形参,使用**定义个数可变的关键字形参,结果为一个字典
# 函数的定义时的可变位置参数
def fun(*args):
print(args)
fun(10)
fun(10, 20)
def fun1(**args):
print(args)
fun1(a=10)
fun1(a=10, b=20, c=30)
"""个数可变的位置参数只能有一个,个数可变的关键字参数也只能有一个,不然会报错
在一个函数的定义过程当中,既有个数可变的关键字形参,也有个数可变的位置参数
要求个数可变的位置参数放在个数可变的关键字参数之前
def fun(*args,**args):
pass
"""
变量的作用域
程序代码能访问该变量的区域,根据变量的有效范围可分为
1、局部变量:在函数内定义并使用的变量,只在函数内部有效,局部变量使用global声明,这个变量就会成全局变量
2、全局变量:函数体外定义的变量,可用于函数内外
"""这里的c就是局部变量,形式参数a,b也是局部变量,只能在函数内使用
"""
def fun(a, b):
c = a+b
print(c)
"""name的作用范围为函数的内部和外部都可以使用,所以name是全局变量
"""
name = 'qq'
print(name)
def fun2():
print(name)
fun2()
def fun3():
# 函数内部定义的是局部变量,当变量被global修饰时,就变成了全局变量
global age
age = 20
print(age)
fun3()
print(age)
递归函数
什么是递归函数?
如果在一个函数的函数体内调用了该函数本身,这个函数就称为递归函数
递归的组成部分?
递归调用与递归终止条件
递归的调用过程
1、每递归调用一次函数,都会在栈内存分配一个栈帧
2、没执行完一次函数,都会释放相应的空间
递归的优缺点
缺点:占内存多,效率低下
优点:思路和代码简单
使用递归求6的阶乘代码实现
def fac(n):
if n == 1:
return 1
else:
return n*fac(n-1)
print(fac(6))
使用递归来求斐波那契数代码实现:
# n就是我们要求的斐波那契额的数
def fib(n):
if n == 1:
return 1
elif n == 2:
return 1
else:
return fib(n-1)+fib(n-2)
# 斐波那契第六位上的数字
result = fib(6)
print(result)
print("----------------")
# 输出前6位斐波那契数
for i in range(1, 7):
print(fib(i))