Python学习-基础语法篇

python学习笔记

列表

# 定义一个列表 aa
>>> aa = [1, 2, 3, 4, 5, 'hhh']
# 打印一个列表
>>> print(aa)
[1, 2, 3, 4, 5, 'hhh']
# 下标获取值
>>> length = len(aa)
>>> aa[length - 1]
'hhh'
>>> aa[-1]
'hhh'
>>> aa[-2]
5
# 截取值
>>> aa[0:3]
[1, 2, 3]
>>> aa[3-4]
'hhh'
>>> aa[3:4]
[4]
>>> aa[3:6]
[4, 5, 'hhh']
>>> aa[3:]
[4, 5, 'hhh']
>>> aa[:3]
[1, 2, 3]
>>> aa[0:3:2]
[1, 3]
>>> aa[::2]
[1, 3, 5]
>>> aa[::-2]
['hhh', 4, 2]
>>> aa[::-1]
['hhh', 5, 4, 3, 2, 1]

列表 增删改查

# 新增元素 在末尾新增
>>> aa.append("ppp") #新增一个元素
>>> aa
[1, 2, 3, 4, 5, 'hhh', 'ppp']
>>> aa.extend(["6","7",]) # 新增多个元素
>>> aa
[1, 2, 3, 4, 5, 'hhh', 'ppp', '6', '7']
# len(s) 表示列表末尾
>>> s = ["one", "two"]
>>> s
['one', 'two']
>>> s[len(s):] = [1,2,3]
>>> s
['one', 'two', 1, 2, 3]
# 插入元素 insert 指定下标 元素值
>>> s = [1,3,4,5]
>>> s
[1, 3, 4, 5]
>>> s.insert(1, 2)
>>> s
[1, 2, 3, 4, 5]
>>> s.insert(0, 0)
>>> s
[0, 1, 2, 3, 4, 5]
>>> s.insert(len(s), 6)
>>> s
[0, 1, 2, 3, 4, 5, 6]
>>> len(s) # 表示列表末尾的下标值
7
>>> s
[0, 1, 2, 3, 4, 5, 6]
>>> aa
[1, 2, 3, 4, 5, 'hhh', 'ppp', '6', '7']
# 删除指定元素的值,存在多个元素,删除最小下标的值
>>> aa.remove("ppp")
>>> aa
[1, 2, 3, 4, 5, 'hhh', '6', '7']
# pop删除下标的值
>>> aa.pop(5)
'hhh'
>>> aa
[1, 2, 3, 4, 5, '6', '7']
# 清空列表
>>> aa.clear()
>>> aa
[]
# 改/替换 列表是可变的 字符串是不可变的
>>> aa = [1, 2, 3, 4, 5, 'hhh']
>>> aa[5] = "ppp"
>>> aa
[1, 2, 3, 4, 5, 'ppp']
# 替换连续的元素 把下标3以后的元素全部替换
>>> aa[3:] = ["aaa", "bbb", "ccc"]
>>> aa
[1, 2, 3, 'aaa', 'bbb', 'ccc']
# 列表排序 sort()正序 颠倒reverse()
>>> nums = [3, 1, 5, 8, 4, 3, 6]
>>> nums.sort()
>>> nums
[1, 3, 3, 4, 5, 6, 8]
>>> nums.reverse()
>>> nums
[8, 6, 5, 4, 3, 3, 1]
>>> aa
[1, 2, 3, 'aaa', 'bbb', 'ccc']
>>> aa.reverse()
>>> aa
['ccc', 'bbb', 'aaa', 3, 2, 1]
# 直接sort reverse=True
>>> nums = [3, 1, 5, 8, 4, 3, 6]
>>> nums.sort(reverse=True)
>>> nums
[8, 6, 5, 4, 3, 3, 1]
# 查找某个元素出现的次数
>>> nums
[8, 6, 5, 4, 3, 3, 1]
>>> nums.count(3)
2
# 查找,某个元素的索引值
>>> aa
['ccc', 'bbb', 'aaa', 3, 2, 1]
>>> aa.index("aaa")
2
获取索引,并替换元素值
>>> aa[aa.index("aaa")] = "AAA"
>>> aa
['ccc', 'bbb', 'AAA', 3, 2, 1]
# 查找索引值 指定开始索引 结束索引
index(3,start,end)
>>> nums = [3, 1, 5, 8, 4, 3, 6]
>>> nums.index(3)
0
>>> nums.index(3, 1, 6)
5
# copy()拷贝列表 浅拷贝
>>> nums
[3, 1, 5, 8, 4, 3, 6]
>>> nums_copy1 = nums.copy()
>>> nums_copy1
[3, 1, 5, 8, 4, 3, 6]
# 另一种方法
>>> nums_copy2 = nums[:]
>>> nums_copy2
[3, 1, 5, 8, 4, 3, 6]

列表的加法和乘法

# 列表的加法 和 乘法
>>> s = [1, 2, 3]
>>> t = [4,5,6]
>>> s + t
[1, 2, 3, 4, 5, 6]
>>> s * 3
[1, 2, 3, 1, 2, 3, 1, 2, 3]

# 嵌套列表 二维列表
>>> matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> matrix
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
# 访问嵌套列表
>>> for i in matrix :
	for each in i:
		print(each)
1
2
3
4
5
6
7
8
9
>>> for i in matrix :
	for each in i:
		print(each, end=' ')
        
1 2 3 4 5 6 7 8 9 
>>> for i in matrix :
	for each in i:
		print(each, end=' ')# end' '指定结尾为空格
	print() # 换行

1 2 3 
4 5 6 
7 8 9 
>>> matrix[0]
[1, 2, 3]
>>> matrix[0][0]
1
>>> matrix[1][1]
5

>>> A = [0] * 3
>>> A
[0, 0, 0]
>>> for i in range(3):
	A[i] = [0] * 3
>>> A
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
# 高级错误!
>>> B = [[0] * 3] * 3
>>> B
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
# 修改下标值
>>> A[1][1] = 1
>>> A
[[0, 0, 0], [0, 1, 0], [0, 0, 0]]
>>> B[1][1] = 1
>>> B
[[0, 1, 0], [0, 1, 0], [0, 1, 0]]
# B 显示错误!

# is 运算符 同一性
>>> x = "kobe"
>>> y = "kobe"
>>> x is y
True
>>> x = [1, 2, 3]
>>> y = [1, 2, 3]
>>> x is y
False
python对于不同对象的存储机制是不一样的。
字符串是不可变的,列表是可变的
>>> A
[[0, 0, 0], [0, 1, 0], [0, 0, 0]]
>>> A[0] is A[1]
False
>>> A[1] is A[2]
False
>>> B
[[0, 1, 0], [0, 1, 0], [0, 1, 0]]
>>> B[1] is B[2]
True
>>> B[0] is B[1]
True

image-20220517104644882

变量不是盒子 ,相当于引用

image-20220517105017816

# 如上图 变量是引用
>>> x = [1, 2, 3]
>>> y = x
>>> x[1] = 1
>>> x
[1, 1, 3]
>>> y
[1, 1, 3]
浅拷贝

image-20220517105245159

# 浅拷贝 如上图:
>>> x = [1, 2, 3]
>>> y = x.copy()
>>> x[1] = 1
>>> x
[1, 1, 3]
>>> y
[1, 2, 3]
>>> # copy是拷贝整个列表对象,而不是变量的引用

#利用切片拷贝 属于浅拷贝 copy 也是
>>> x = [1, 2, 3]
>>> y = x[:]
>>> x[1] = 1
>>> x
[1, 1, 3]
>>> y
[1, 2, 3]

# 对于嵌套列表 浅拷贝(copy\切片)是不行的
>>> x = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> y = x.copy()
>>> x[1][1] = 0
>>> x
[[1, 2, 3], [4, 0, 6], [7, 8, 9]]
>>> y
[[1, 2, 3], [4, 0, 6], [7, 8, 9]]
# 浅拷贝是拷贝了外层的对象,嵌套的对象是引用 如下图:

image-20220517105959722

深拷贝

image-20220517110630616

# 引用copy模块 import copy
x.copy() 列表的copy方法  浅拷贝
copy.copy(x) copy模块的copy函数 也属于浅拷贝
>>> import copy
>>> x = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> y = copy.copy(x)
>>> x[1][1] = 0
>>> x
[[1, 2, 3], [4, 0, 6], [7, 8, 9]]
>>> y
[[1, 2, 3], [4, 0, 6], [7, 8, 9]]
# 深拷贝:
>>> import copy
>>> x = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> y = copy.deepcopy(x)
>>> x[1][1] = 0
>>> x
[[1, 2, 3], [4, 0, 6], [7, 8, 9]]
>>> y
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
列表推导式
# 列表推导式
一个数值列表,使其元素值*2。
# 笨方法:
>>> oh = [1, 2, 3, 4, 5]
>>> for i in range(len(oh)): #len(oh)获取列表下标长度
	oh[i] = oh[i] * 2
>>> oh
[2, 4, 6, 8, 10]

# 正片 来了
# 效率:列表推导式 比 循环语句快一倍左右
>>> oh = [1, 2, 3, 4, 5]
>>> oh = [i * 2 for i in oh]
>>> oh
[2, 4, 6, 8, 10]

>>> x = [i for i in range(10)]
>>> x
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> x = [i + 1 for i in range(10)]
>>> x
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> x.clear()
>>> x
[]
>>> for i in range(10):
	x.append(i+1)
>>> x
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# 处理字符串
>>> y = [o * 2 for o in "Kobe"]
>>> y
['KK', 'oo', 'bb', 'ee']
# 转换为Unicode编码并保存列表中
ord内置函数:将单个字符串转换为对应的编码
>>> code = [ord(c) for c in "Kobe"]
>>> code
[75, 111, 98, 101]
# 提取x列表中的元素。  
   x = [[1, 2, 3], 
		[4, 5, 6], 
        [7, 8, 9]] 
# 提取 2 5 8
>>> x = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> col2 = [row[1] for row in x]
>>> col2
[2, 5, 8]
# 提取 1 5 9 ,len(x)列表x的下标=3 (0,1,2)
>>> diag = [x[i][i] for i in range(len(x))]
>>> diag
[1, 5, 9]
# 提取 3 5 7 
>>> gg = [x[i][-i-1] for i in range(len(x))]
>>> gg
[3, 5, 7]
# 
>>> s = [[0] * 3 for i in range(3)]
>>> s
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
>>> s[0][0] = 1
>>> s
[[1, 0, 0], [0, 0, 0], [0, 0, 0]]

# if 分句 执行顺序 for>if>i
>>> even = [i for i in range(10) if i % 2 == 0]
>>> even
[0, 2, 4, 6, 8]
>>> even = [i + 1 for i in range(10) if i % 2 == 0]
>>> even
[1, 3, 5, 7, 9]
# 取出字母k开头的元素
>>> words = ["great", "kobe", "exec", "hhhh", "kd"]
>>> kwords = [w for w in words if w[0] == "k" ]
>>> kwords
['kobe', 'kd']
# 嵌套循环 -- 嵌套列表 转换为二维列表
>>> x = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> flatten = [col for row in x for col in row ]
>>> flatten
[1, 2, 3, 4, 5, 6, 7, 8, 9]
# 用for循环表示
>>> flatten = []
>>> for row in x:
	for col in row:
		flatten.append(col)
	
>>> flatten
[1, 2, 3, 4, 5, 6, 7, 8, 9]
加固一下:
>>> [x + y for x in "kobe" for y in "KOBE"]
['kK', 'kO', 'kB', 'kE', 'oK', 'oO', 'oB', 'oE', 'bK', 'bO', 'bB', 'bE', 'eK', 'eO', 'eB', 'eE']
>>> _ = [] # 临时变量 _ 表示
>>> for x in "kobe":
	for y in "KOBE":
		_.append(x + y)
	
>>> _
['kK', 'kO', 'kB', 'kE', 'oK', 'oO', 'oB', 'oE', 'bK', 'bO', 'bB', 'bE', 'eK', 'eO', 'eB', 'eE']
# for 后 边加 if判断。
[[x, y] for x in range(10) if x % 2 == 0 for y in range(10) if y % 3 == 0]
[[0, 0], [0, 3], [0, 6], [0, 9], [2, 0], [2, 3], [2, 6], [2, 9], [4, 0], [4, 3], [4, 6], [4, 9], [6, 0], [6, 3], [6, 6], [6, 9], [8, 0], [8, 3], [8, 6], [8, 9]]
>>> _ = []
>>> for x in range(10):
	if x % 2 == 0:
		for y in range(10):
			if y % 3 == 0:
				_.append([x, y])			
>>> _
[[0, 0], [0, 3], [0, 6], [0, 9], [2, 0], [2, 3], [2, 6], [2, 9], [4, 0], [4, 3], [4, 6], [4, 9], [6, 0], [6, 3], [6, 6], [6, 9], [8, 0], [8, 3], [8, 6], [8, 9]]

元组

列表 - [元素1, 元素2, 元素3]

元组 - (元素1, 元素2, 元素3)

# 定义元组
>>> the = (1, 2, 3, 4, 5, "上山大老鼠")
>>> the
(1, 2, 3, 4, 5, '上山大老鼠')
不加括号也行,用逗号隔开
>>> the = 1, 2, 3, 4, 5, "上山大老鼠"
>>> the
(1, 2, 3, 4, 5, '上山大老鼠')
>>> the[0]
1
>>> the[-1]
'上山大老鼠'
>>> the[1] = 10 # 元组不可变
Traceback (most recent call last):
  File "<pyshell#312>", line 1, in <module>
    the[1] = 10
TypeError: 'tuple' object does not support item assignment
# 切片同样试用元组
>>> the[:]
(1, 2, 3, 4, 5, '上山大老鼠')
>>> the[:3]
(1, 2, 3)
>>> the[::2]
(1, 3, 5)
>>> the[::-1]
('上山大老鼠', 5, 4, 3, 2, 1)
>>> nums = (3, 1, 9, 6, 8, 3, 5, 3)
>>> nums.count(3)
3
>>> heros = ("蜘蛛侠", "绿巨人", "黑寡妇")
>>> heros.index("黑寡妇")
2
>>> s = (1,2,3)
>>> t = (4,5,6)
>>> s + t
(1, 2, 3, 4, 5, 6)
>>> s * 3
(1, 2, 3, 1, 2, 3, 1, 2, 3)
>>> w = s, t # 嵌套元组
>>> w
((1, 2, 3), (4, 5, 6))
>>> for i in s: # 元组支持迭代
	print(i)
	
1
2
3
>>> for i in w: # 嵌套元组的嵌套循环 
	for each in i:
		print(each)
		
1
2
3
4
5
6
>>> s = (1, 2, 3, 4, 5)
>>> [each * 2 for each in s] #元组的列表推导式
[2, 4, 6, 8, 10]
>>> (each * 2 for each in s) #没有元组推导式
<generator object <genexpr> at 0x000002DEC4C53BA0>
# 生成只有一个元素的元组
>>> x = (520)
>>> x
520
>>> type(x) 查看类型
<class 'int'>
>>> x = (520,) # 正确写法 后边加 , 号
>>> x
(520,)
>>> type(x)
<class 'tuple'>

# 打包和解包 
>>> t = (123, "FISH", 3.14)
>>> x, y, z = t
>>> x
123
>>> y
'FISH'
>>> z
3.14
# 列表同样可以
>>> t = [123, "FISH", 3.14]
>>> x, y, z =t
>>> x
123
>>> y
'FISH'
>>> z
3.14
字符串也是OK
>>> a, b, c, d = "KOBE"
>>> a
'K'
>>> b
'O'
>>> c
'B'
>>> d
'E'
注意 变量跟 后边的保持一致。除非 *c 小技巧
>>> a, b, *c = "KOBE"
>>> a
'K'
>>> b
'O'
>>> c
['B', 'E']
# 多个赋值
>>> x, y = 10, 20
>>> x
10
>>> y
20
原理:
>>> _ = (10, 20)
>>> x, y = _
>>> x
10
>>> y
20
# 元组是不可变的,如果元组的元素是可变的列表,那么就可以改变元组的可变列表中的元素。
>>> s = [1, 2, 3]
>>> t = [4, 5, 6]
>>> w = (s, t)
>>> w
([1, 2, 3], [4, 5, 6])
>>> w[0][0] = 0
>>> w
([0, 2, 3], [4, 5, 6])

字符串

字符串不可变

判断字符串是不是回文数,正读 倒读 一样 就是回文数
>>> x = "12321"
>>> "是回文数" if x == x[::-1] else "不是回文数"
'是回文数'
>>> x = "123"
>>> "是回文数" if x == x[::-1] else "不是回文数"
'不是回文数'


大小写字母 切换

方法:

# 整个字符串的首字母变大写 其余变小写 capitalize()
>>> x = "I love YoU"
>>> x.capitalize()
'I love you'
>>> x # 字符串不可变
'I love YoU'

# 所有字符变为小写 casefold() 
>>> x.casefold()
'i love you'
# 每个单词首字母为大写 其他小写 title()
>>> x.title()
'I Love You'
# 大小写 和原来的反转 swapcase()
>>> x.swapcase()
'i LOVE yOu'
# 所有字母变为大写 upper()
>>> x.upper()
'I LOVE YOU'
# 所有字母变为小写  lower()
>>> x.lower()
'i love you'
左中右对齐
注意width值要比源字符串长度大,否则输出源字符串。
 fillchar='' 默认为空格 可以用其他
# center(width, fillchar='') 
>>> x = "有内鬼,停止交易!"
>>> x.center(5)
'有内鬼,停止交易!'
>>> x.center(15)
'   有内鬼,停止交易!   '
>>> x.center(15, "-") # fillchar='' 默认为空格 指定 -
'---有内鬼,停止交易!---'

# ljust(width, fillchar='')
>>> x.ljust(15)
'有内鬼,停止交易!  
# rjust(width, fillchar='')
>>> x.rjust(15)
'      有内鬼,停止交易!'
# zfill(width)
>>> x.zfill(15)
'000000有内鬼,停止交易!'
>>> "520".zfill(5)
'00520'
>>> "-520".zfill(5)
'-0520'
查找
# 查找字符在字符串中出现的次数              count(sub[,start[,end]])
>>> x = "上海自来水来自海上"
>>> x.count("海")
2
>>> x.count("海", 0, 5)
1
# find(sub[,start[,end]]) 从左往右查找第一个字符的下标
>>> x.find("海")
1
>>> x.find("HH") #找不到值会返回 -1
-1
# rfind(sub[,start[,end]]) 从右往左查找第一个字符的下标
>>> x.rfind("海")
7
# index(sub[,start[,end]])
>>> x.index("海")
1
>>> x.index("HH") #找不到值会返回异常
Traceback (most recent call last):
  File "<pyshell#7>", line 1, in <module>
    x.index("HH")
ValueError: substring not found
    
#rindex(sub[,start[,end]])
>>> x.rindex("海")
7
替换
# expandtabs([tabsize=8]) 使用空格替换制表符
>>> code = """
	print("I love YoU")
    print("I love my wife")"""
>>> new_code = code.expandtabs(4)
>>> print(new_code)

    print("I love YoU")
    print("I love my wife")
    
# replace(old,new,count=-1) count默认值-1 全部替换
>>> "在么!我在你家楼下,快点下来!!".replace("在么","想你")
'想你!我在你家楼下,快点下来!!'

# translate(table) # 密码文 相当于 个人理解 哈哈
建立的表格内容替换,也就是如果有语句中含有表格内的内容就会被替换,没有就不替换
>>> table = str.maketrans("ABCDEFG", "1234567")
>>> "welcome to NBA".translate(table)
'welcome to N21'
>>> table = str.maketrans("ABCDEFG", "1234567", "o") # 最后忽略字母 o 。
>>> "welcome to NBA".translate(table)
'welcme t N21'
>>> "welcome to NBA".translate(str.maketrans("ABCDEFG", "1234567", "to"))
'welcme  N21'
>>> "welcome to NBA".translate(str.maketrans("ABCDEFG", "1234567", "t"))
'welcome o N21'
判断

判断字符串 返回的都是布尔值 True & False

判断字符是否在字符串的开头
# startswith(prefix[,start[,end]])
>>> x = "我待python"
>>> x.startswith("我")
True
>>> x.startswith("你")
False
>>> x.startswith("我",1) # 可以指定索引起始值
False
>>> x.startswith("待",1)
True
判断字符是否在字符串的结尾
#endswith(suffix,[,start[,end]])
>>> x.endswith("python")
True
>>> x.endswith("py")
False
>>> x.endswith("py", 0, 4)
True
条件判断:
>>> x = "她爱Python"
>>> if x.startswith(("你", "我", "她")):
	print("总有人喜欢Python")

总有人喜欢Python

判断字符串中索引单词首写字母大写,其他小写
# istitle()
>>> x = "I love Python"
>>> x.istitle()
False

判断字符串所有字母都是大写
# isupper()
>>> x.isupper()
False
>>> x.upper().isupper() # upper()将字串变为大写 再进行isupper判断
True

判断字符串所有字母都是小写
# islower()
同上。。

判断字符串是否都是字母
# isalpha()
>>> x.isalpha() # 空格不是字母!
False
>>> "IlovePyhton".isalpha()
True

判断是否是空字符串
# isspace()
>>> "	\n".isspace() # 空格 /n 都是空字符
True
>>> " ".isspace()
True

判断是否都是可打印的
# isprintable()
>>> "I love you\n".isprintable() # /n 不可打印
False

判断数字 三个都是
# isdecimal()
# isdigit()
# isnumeric()

>>> x = "12345" # 为正常十进制 都一样
>>> x.isdecimal()
True
>>> x.isdigit()
True
>>> x.isnumeric()
True

>>> x = "2²" # isdecimal 不可以
>>> x.isdecimal()
False
>>> x.isnumeric()
True
>>> x.isdigit()
True

>>> x = "①" # isdecimal 不可以 罗马也不行
>>> x.isdecimal() # 罗马也不行
False
>>> x.isdigit() #  罗马也不行
True
>>> x.isnumeric()
True

>>> x = "一二" # isnumeric可以
>>> x.isdecimal()
False
>>> x.isdigit()
False
>>> x.isnumeric()
True


集大成者 
# isalnum()
只要满足 isalpha()或者isdecimal()或者isdigit()或者isnumeric() 其中一个为True,isalnum()即为True。

判断是否是合法的python标识符 相当于变量名的标准
# isidentifier()
>>> "I love you".isidentifier()
False
>>> "I_love_you".isidentifier()
True
>>> "kobe24".isidentifier()
True
>>> "24kobe".isidentifier()
False

判断是否是py的保留标识符 if for while ...
>>> import keyword
>>> keyword.iskeyword("if")
True
>>> keyword.iskeyword("py")
False
截取
相当于剔除 chars=None 默认为空格
lstrip()  左侧不留空白
>>> "     左侧不要留白".lstrip()
'左侧不要留白'

rstrip() 右侧不留空白
>>> "右侧不要留白       ".rstrip()
'右侧不要留白'

strip() 左右都不要留白
>>> "     左右都不要留白       ".strip()
'左右都不要留白'

以上三个 (chars=None)
>>> "www.baidu.com".lstrip("wcom.")
'baidu.com'
>>> "www.baidu.com".rstrip("wcom.")
'www.baidu'
>>> "www.baidu.com".strip("wcom.")
'baidu'

指定删除的前缀 3.9+版本才不会报错
# removeprefix(prefix)
"www.baidu.com".removeprefix("www.")
'baidu.com'

指定删除的后缀 3.9+版本才不会报错
# removesuffix(suffix)
"www.baidu.com".removesuffix(".com")
'www.baidu'

拆分 & 拼接
从左到右指定分割符 组成三元组
# partition(sep)
"www.baidu.com".partition(".")
('www', '.', 'baidu.com')

从右到左指定分割符 组成三元组
# rpartition(sep)
"www.baidu.com".rpartition(".")
('www.baidu', '.', 'com')

# split(sep=None,maxsplit=-1)
# rsplit(sep=None,maxsplit=-1)
"苟日新,日日新,又日新".split()
['苟日新,日日新,又日新']
"苟日新 日日新 又日新".split()
['苟日新', '日日新', '又日新']
"苟日新,日日新,又日新".split(',')
['苟日新', '日日新', '又日新']
"苟日新,日日新,又日新".rsplit(',')
['苟日新', '日日新', '又日新']
"苟日新,日日新,又日新".split(',',1)
['苟日新', '日日新,又日新']
"苟日新,日日新,又日新".rsplit(',',1)
['苟日新,日日新', '又日新']
"苟日新\n日日新\n又日新".rsplit('\n')
['苟日新', '日日新', '又日新']
换行符在各系统下的表示:
\n linux \r macos \r\n windows
# splitlines() 将字符以 换行 进行切割,生成列表
"苟日新\n日日新\r又日新".splitlines()
['苟日新', '日日新', '又日新']
"苟日新\n日日新\r\n又日新".splitlines()
['苟日新', '日日新', '又日新']
True 包含换行符
"苟日新\n日日新\r\n又日新".splitlines(True)
['苟日新\n', '日日新\r\n', '又日新']


# join(iterable)
".".join(["www", "baidu", "com"])
'www.baidu.com'
"^".join(("K", "ob", "e"))
'K^ob^e'

s = "kobe"
s += s
s
'kobekobe'
"".join(("kobe", "kobe"))
'kobekobe'
format

格式化字符串

# format() 使用{}占位 
age = 18
"我今年 age 岁"
'我今年 age 岁'
"我今年 {} 岁".format(age)
'我今年 18 岁'
"1+2={}, 2的平方是{}, 3的立方是{}".format(1+2, 2*2, 3*3*3)
'1+2=3, 2的平方是4, 3的立方是27'
# format也有索引值。也可以引用多次
"{}看到{}就很激动".format("你", "美女")
'你看到美女就很激动'
"{1}看到{0}就很激动".format("你", "美女")
'美女看到你就很激动'
"{0}{0}{1}{1}".format("是", "非")
'是是非非'
我叫{name},我爱{a}".format(name="小李", a="Python")
'我叫小李,我爱Python'
输出{}
"{},{},{}".format(1, {}, 2)
'1,{},2'
"{},{{}},{}".format(1, 2)
'1,{},2'

align

image-20220519164318278

"{:^}".format(250)
'250'
"{:^5}".format(250)
' 250 '
"{1:>10}{0:10}".format(520, 250)
'       250       520'
"{1:>10}{0:<10}".format(520, 250)
'       250520       '
"{left:>10}{right:<10}".format(right=520, left=250)
'       250520       '
{0:010} 只对数字有用
"{:010}".format(520)
'0000000520'
"{:010}".format(-520)
'-000000520'
"{:0=10}".format(520)
'0000000520'
"{:%=10}".format(520)
'%%%%%%%520'
"{1:%>10}{0:%<10}".format(520, 250)
'%%%%%%%250520%%%%%%%'

image-20220519185951463

# + - 空格 只对数字类型有效
"{:+}{:-}".format(520, -250)
'+520-250'
# , _ 对千分位进行分割
"{:,}".format(1234)
'1,234'
"{:_}".format(1234)
'1_234'
"{:_}".format(123)
'123'
"{:,}".format(123456789)
'123,456,789'
# 小数点精确
"{:.2f}".format(3.1415)
'3.14'
"{:.2g}".format(3.1415)
'3.1'
"{:.4}".format("I love you")
'I lo'
"{:.4}".format(520) # 不能对整数使用
Traceback (most recent call last):
  File "<pyshell#25>", line 1, in <module>
    "{:.4}".format(520)
ValueError: Precision not allowed in integer format specifier
"{:.2}".format("520") # ""成字符串了
'52'

适用于整数:

image-20220519191426550

# 列子: 
"{:b}".format(80)
'1010000'
"{:c}".format(80)
'P'
"{:d}".format(80)
'80'
"{:o}".format(80)
'120'
"{:x}".format(80)
'50'
# #号是显示前缀 显示b c o x d信息
"{:#b}".format(80)
'0b1010000'
"{:#o}".format(80)
'0o120'
"{:#x}".format(80)
'0x50'

复数浮点数类型

image-20220519192025152

# 例子
"{:e}".format(3.1415)
'3.141500e+00'
"{:E}".format(3.1415)
'3.141500E+00'
"{:f}".format(3.1415)
'3.141500'
"{:g}".format(3.1415)
'3.1415'
"{:g}".format(123456789)
'1.23457e+08'
"{:g}".format(1234.56789)
'1234.57'
"{:%}".format(0.98)
'98.000000%'
"{:.2%}".format(0.98)
'98.00%'
"{:.{prec}f}".format(3.1415, prec=2)
'3.14'
"{:{fill}{align}{width}.{prec}{ty}}".format(3.1415, fill='+', align='^', width=10, prec=3, ty='g')
'+++3.14+++'
"{:+^10.3g}".format(3.1415)
'+++3.14+++'
f-字符串

f-string

image-20220519194439609

F f 大小f均可以。
f-string 方法:
age = 18
f"我今年 {age} 岁"
'我今年 18 岁'
f"1+2={1+2}, 2的平方是{2*2}, 3的立方是{3*3*3}"
'1+2=3, 2的平方是4, 3的立方是27'
"我今年 {} 岁".format(age) # format方法:
"{:010}".format(-520) # format方法:
'-000000520'
F"{-520:010}"
'-000000520'

f"{123456789:,}"
'123,456,789'

fill = '+'
align = '^'
width = 10
prec = 3
ty = 'g'
f"{3.1415:{fill}{align}{width}.{prec}{ty}}"
'+++3.14+++'

"{:{fill}{align}{width}.{prec}{ty}}".format(3.1415, fill='+', align='^', width=10, prec=3, ty='g') # format方法:
'+++3.14+++'


序列

列表 元组 字符串的特点:

共同点:

  • 都可以通过索引获取每一个元素

  • 第一个元素的索引值都是0

  • 都可以通过切片的方法获取一个范围内元素的集合

  • 都有很多的运算符

列表 元组 字符串 统称为 序列 !!!

根据元素可不可以修改可以把序列分为 可变序列和不可变序列。

可变序列:列表

不可变序列:字符串 元组

+ 表示 拼接
* 表示 拷贝
[1, 2, 3] + [4, 5, 6]
[1, 2, 3, 4, 5, 6]
(1,2,3) + (4,5,6)
(1, 2, 3, 4, 5, 6)
"123" + "456"
'123456'
[1, 2, 3] * 2
[1, 2, 3, 1, 2, 3]
(1, 2, 3) * 2
(1, 2, 3, 1, 2, 3)
"123" * 2
'123123'

坑:
在python中每一个对象都有是哪个基本属性:
1.唯一标志(id随着对象创建的时候就有的,不可修改,不会重复)
2.类型
3.值 
s = [1, 2, 3]
id(s)
2350282056448
s *= 2
s
[1, 2, 3, 1, 2, 3]
id(s)
2350282056448 # id值不变 可变序列id值不变

t = (1, 2, 3)
id(t)
2350312044288
t *= 2
t
(1, 2, 3, 1, 2, 3)
id(t)
2350311075424 # id值变了 不可变序列id值变了
# is & is not 检测对象id值是否相等,从而判断是否是同一个对象,也成为同一性运算符。返回布尔值
 x = "kobe"
y = "kobe"
x is y
True
x = [1, 2, 3]
y = [1, 2, 3]
x is y # 因为列表可变 
False


# in & not in 判断包含问题,某个元素是否在序列中

"鱼" in "鱼C"
True
"Fish" in "Fishc"
True
"C" not in "ABC"
False

# del用于删除一个或多个指定的对象
x = "ABC"
y = [1, 2, 3]
del x, y
x
Traceback (most recent call last):
  File "<pyshell#115>", line 1, in <module>
    x
NameError: name 'x' is not defined
y
Traceback (most recent call last):
  File "<pyshell#116>", line 1, in <module>
    y
NameError: name 'y' is not defined. Did you mean: 'ty'?
#del还可以删除可变序列中的指定元素
x = [1, 2, 3, 4, 5]
del x[1:4]
x
[1, 5]
切片也行:
y = [1, 2, 3, 4, 5]
y[1:4] = []
y
[1, 5]

x = [1, 2, 3, 4, 5]
del x[::2]
x
[2, 4]
实现 clear的效果
x = [1, 2, 3, 4, 5]
x.clear()
x
[]
y = [1, 2, 3, 4, 5]
del y[:]
y
[]

序列函数

列表,元组和字符串相互转换的函数:

-- list(), tuple(), str()
# 可迭代对象转换为列表 用list、
list("Kobe")
['K', 'o', 'b', 'e']
list((1, 2, 3, 4, 5))
[1, 2, 3, 4, 5]

# 可迭代对象转换为元组 用tuple()、
tuple("Kobe")
('K', 'o', 'b', 'e')
tuple([1, 2, 3, 4, 5])
(1, 2, 3, 4, 5)

# 可迭代对象转换为字符串 用str()、
str([1, 2, 3, 4, 5])
'[1, 2, 3, 4, 5]'
str((1, 2, 3, 4, 5))
'(1, 2, 3, 4, 5)'

min() & max() 函数

image-20220520081509271

-- min() & max() 函数对比传入的参数,并返回最大值和最小值。
s = [1, 2, 3, 4, 5]
min(s)
1
t = "FishC" # 比较每个字符串的编码值 小写字母在大写字母之前。 
max(t)
's'
# 处理空对象
s = []
min(s)
Traceback (most recent call last):
  File "<pyshell#11>", line 1, in <module>
    min(s)
ValueError: min() arg is an empty sequence
min(s, default="是空的,,")
'是空的,,'

min(1, 2, 3, 4, 0, 6)
0
max(1, 2, 3, 4, 0, 6)
6
len() & sum()
-- len() & sum() 函数
#len是有长度限制的 32位是2的31次方减一,64位是2的63次方减一。超多就报错
len(range(2 ** 100)) 
Traceback (most recent call last):
  File "<pyshell#18>", line 1, in <module>
    len(range(2 ** 100))
OverflowError: Python int too large to convert to C ssize_t
    
s = [1, 0, 0, 8, 6]
sum(s)
15
sum(s, start=100)
115
sorted() & reversed()
-- sorted() & reversed()函数用于列表的元素进行原地排序
# sorted函数不会改变原来的列表
s = [1, 0, 0, 8, 6]
sorted(s)
[0, 0, 1, 6, 8]
s
[1, 0, 0, 8, 6]
# 如果用s.sort方法列表就会改变。
s.sort()
s
[0, 0, 1, 6, 8]
sorted(s, reverse=True) # 加参数 反转了
[8, 6, 1, 0, 0]
# key 干预排序的参数
t = ["FishC", "Apple", "Pen", "Book", "banana"]
sorted(t)
['Apple', 'Book', 'FishC', 'Pen', 'banana']
sorted(t, key=len)
['Pen', 'Book', 'FishC', 'Apple', 'banana']
# t.sort方法
t.sort(key=len)
t
['Pen', 'Book', 'FishC', 'Apple', 'banana']
sorted("FishC")
['C', 'F', 'h', 'i', 's']
sorted((1, 2, 3, 0, 7, 5))
[0, 1, 2, 3, 5, 7]


# reversed
s = [1, 2, 5, 8, 0]
reversed(s)
<list_reverseiterator object at 0x000002398D8D6560>
list(reversed(s))
[0, 8, 5, 2, 1]
s
[1, 2, 5, 8, 0]
s.reverse()
s
[0, 8, 5, 2, 1]
list(reversed("FishC"))
['C', 'h', 's', 'i', 'F']
list(reversed((1, 2, 4, 8, 6)))
[6, 8, 4, 2, 1]
list(reversed(range(0, 10)))
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
all() & any()
-- all() & any()函数 
all函数判断可迭代对象中是都所有元素的值都为真。
any函数判断可迭代对象中是否存在某个元素的值都为真。
x = [1, 1, 0]
y = [1, 1, 9]
all(x)
False
all(y)
True
any(x)
True
any(y)
True
enumerate()
-- enumerate()函数用于返回一个枚举对象,它的功能是将可迭代对象中的每个元素即从0开始的序号共同构成一个二元组的列表
#例子
seasons = ["Spring", "Summer", "Fall", "Winter"]
enumerate(seasons)
<enumerate object at 0x000002398D76A980>
list(enumerate(seasons))
[(0, 'Spring'), (1, 'Summer'), (2, 'Fall'), (3, 'Winter')]
# 指定从 几开始。
list(enumerate(seasons, 10))
[(10, 'Spring'), (11, 'Summer'), (12, 'Fall'), (13, 'Winter')]
zip()
-- zip()函数用于创建一个聚合多个可迭代对象的迭代器,它会将作为参数传入的每个可迭代对象的每个元素依次组成元组,即第i个元组包含来自每个参数的第i个元素。
x = [1, 2, 3]
y = [4, 5, 6]
zipped = zip(x, y)
zipped
<zip object at 0x000002398B9D21C0>
list(zipped)
[(1, 4), (2, 5), (3, 6)]
# 加一个
z = [7, 8, 9]
zipped = zip(x, y, z)
list(zipped)
[(1, 4, 7), (2, 5, 8), (3, 6, 9)]
# 多余的不显示。。
z = "FishC"
zipped = zip(x, y, z)
list(zipped)
[(1, 4, 'F'), (2, 5, 'i'), (3, 6, 's')]
引入itertools模块 显示多余的元素
import itertools
zipped = itertools.zip_longest(x, y, z)
list(zipped)
[(1, 4, 'F'), (2, 5, 'i'), (3, 6, 's'), (None, None, 'h'), (None, None, 'C')]
map()
-- map()函数会根据提供的函数对指定的可迭代对象的每个元素进行运算,并将返回运算结果的迭代器。
# 指定函数ord,作用是转换为编码值,对可迭代对象“FishC”进行ord计算。即:map(指定函数, 可迭代对象)
mapped = map(ord, "FishC")
list(mapped)
[70, 105, 115, 104, 67]
# 指定多个参数(可迭代对象) pow 计算次方
mapped = map(pow, [2, 3, 10], [5, 2, 3])
list(mapped)
[32, 9, 1000]
相当于:
[pow(2, 5), pow(3, 2), pow(10, 3)]
[32, 9, 1000]
# 多余参数不采纳 跟zip类似
list(map(max, [1, 3, 5], [2, 2, 2], [0, 3, 9, 8]))
[2, 3, 9]
filter()
-- filter()函数会根据提供的函数对指定的可迭代对象的每个元素进行运算,并将运算结果为真的元素,以迭代器的形式返回。
# 例子
list(filter(str.islower, "FishC"))
['i', 's', 'h']

总结:

zip:一对一 组合

map:让指定函数对参数进行运算得出全部计算结果

filter:让指定函数对参数进行计算得出真的结果

迭代器 VS 可迭代对象

一个迭代器肯定是一个迭代对象,可迭代对象可以重复是使用,而迭代器则是一次性的。举例说明:

#
mapped = map(ord, "FishC")
for each in mapped:
    print(each)
    
70
105
115
104
67
list(mapped)
[]
# 
mapped = map(ord, "FishC")
list(mapped)
[70, 105, 115, 104, 67]
list(mapped)
[]

iter()

-- iter()函数
# 
x = [1, 2, 3, 4, 5]
iter(x)
<list_iterator object at 0x000002398D8D76D0>
y = iter(x)
type(x)
<class 'list'>
type(y)
<class 'list_iterator'>

next()

-- next()函数 逐个将迭代器中的元素提取出来。
#
next(y)
1
next(y)
2
next(y)
3
next(y)
4
next(y)
5
next(y)
Traceback (most recent call last):
  File "<pyshell#132>", line 1, in <module>
    next(y)
StopIteration

z = iter(x)
next(z, "没有啦")
1
next(z, "没有啦")
2
next(z, "没有啦")
3
next(z, "没有啦")
4
next(z, "没有啦")
5
next(z, "没有啦")
'没有啦'

字典

“字典这个数据结构活跃在所有Python程序的背后,即使你的源码里并没有直接用到它。”

字典是Python中唯一实现映射关系的内置类型。

什么是映射关系?如:摩斯密码

摩斯密码:

image-20220520141525763

在映射类型数据的获取上,字段的效率是要远远快于列表的。

字典定义 {“键”:“值”},通过键写入和读取。

#
x = {"吕布", "关鱼"}
type(x)
<class 'set'> # set 是集合!
# 字典定义 {“键”:“值”} 第一种方式
y = {"吕布":"口口布", "关羽":"关习习"}
type(y)
<class 'dict'>
# 通过键获取对应的值。
y["吕布"]
'口口布'
# 新增
y["刘备"] = "刘baby"
y
{'吕布': '口口布', '关羽': '关习习', '刘备': '刘baby'}


# 定义字典 第二种方式:通过dict函数
b = dict(吕布="口口布", 关羽="关习习", 刘备="刘baby")

#定义字典 第三种方式:通过列表
c = dict([("吕布", "口口布"), ("关羽", "关系系"), ("刘备", "刘baby")])

#第四种:
d = ({"吕布":"口口布", "关羽":"关习习", "刘备":"刘baby"})

# 第五种 混合
e = dict({"吕布":"口口布", "关羽":"关习习"}, 刘备="刘baby")

# 第六种 zip函数
f = dict(zip(["吕布", "关羽", "刘备"], ["口口布", "关系系", "刘baby"]))
f
{'吕布': '口口布', '关羽': '关系系', '刘备': '刘baby'}

# 结果是等价的
y == b == c == d == e == f
True
增删改查:
-- fromkeys(iterable[, values])
# 快速定义一个字典
d = dict.fromkeys("Fish", 250)
d
{'F': 250, 'i': 250, 's': 250, 'h': 250}
# 修改某个键的值
d["F"] = 70
d
{'F': 70, 'i': 250, 's': 250, 'h': 250}
# 找不到键 会新增一个
d["C"] = 80
d
{'F': 70, 'i': 250, 's': 250, 'h': 250, 'C': 80}
# 序列中元素是可以重复的,而字典中的一个键对应一个值,不能重复。
# 删除 s键
d.pop('s')
250
s
d
{'F': 70, 'i': 250, 'h': 250, 'C': 80}
# 删除不存在的键 会抛异常
d.pop("gou")
Traceback (most recent call last):
  File "<pyshell#202>", line 1, in <module>
    d.pop("gou")
KeyError: 'gou'
d.pop("gou", "没有") # 处理异常
'没有'
# popiy=tem()删除最后一个加入字典的键值对。
d.popitem()
('C', 80)
d
{'F': 70, 'i': 250, 'h': 250}
# del 也可以删除 键 和 整个字典
del d['i']
d
{'F': 70, 'h': 250}
del d
d
Traceback (most recent call last):
  File "<pyshell#213>", line 1, in <module>
    d
NameError: name 'd' is not defined. Did you mean: 'id'?
# 只清空字典中的内容
c = dict.fromkeys("FishC", 250)
c
{'F': 250, 'i': 250, 's': 250, 'h': 250, 'C': 250}
c.clear()
c
{}
# 修改
c = dict.fromkeys("FishC")
c
{'F': None, 'i': None, 's': None, 'h': None, 'C': None}
c['s'] = 115
c
{'F': None, 'i': None, 's': 115, 'h': None, 'C': None}

# 修改多个 update
c.update({'i':105, 'h':104}) # 第一种
c
{'F': None, 'i': 105, 's': 115, 'h': 104, 'C': None}
c.update(F='70', C='67') # 第二种
c
{'F': '70', 'i': 105, 's': 115, 'h': 104, 'C': '67'}
# 查找
c['c'] #当键不存在 会报错。
Traceback (most recent call last):
  File "<pyshell#232>", line 1, in <module>
    c['c']
KeyError: 'c'
    
# c['c'] #当键不存在 会报错,用户体验不佳。所以用get(key[, default])
c.get('c', "这里没有c")
'这里没有c'

# setdefault() 找键值,没有会自动给字典添加这个键值。
d
{'F': '70', 'i': '105', 's': '115', 'h': '104', 'C': '67'}
d.setdefault('C', "code")
'67'
d.setdefault('c', "code")
'code'
d
{'F': '70', 'i': '105', 's': '115', 'h': '104', 'C': '67', 'c': 'code'}

items() keys() values()

items() 获取键值对  keys()获取键  values()获取值
# 
d
{'F': '70', 'i': '105', 's': '115', 'h': '104', 'C': '67', 'c': 'code'}
keys = d.keys()
values = d.values()
items = d.items()
items
dict_items([('F', '70'), ('i', '105'), ('s', '115'), ('h', '104'), ('C', '67'), ('c', 'code')])
keys
dict_keys(['F', 'i', 's', 'h', 'C', 'c'])
values
dict_values(['70', '105', '115', '104', '67', 'code'])
# 视图对象:字典内容改变 其也改变
d.pop('c')
'code'
d
{'F': '70', 'i': '105', 's': '115', 'h': '104', 'C': '67'}
items
dict_items([('F', '70'), ('i', '105'), ('s', '115'), ('h', '104'), ('C', '67')])
keys
dict_keys(['F', 'i', 's', 'h', 'C'])
values
dict_values(['70', '105', '115', '104', '67'])
#浅拷贝
e = d.copy()
e
{'F': '70', 'i': '105', 's': '115', 'h': '104', 'C': '67'}


len(d)
5
'C' in d
True
'c' not in d
True
list(d)
['F', 'i', 's', 'h', 'C']
list(d.values())
['70', '105', '115', '104', '67']
# 迭代器iter
e = iter(d)
next(e)
'F'
next(e)
'i'
next(e)
's'
next(e)
'h'
next(e)
'C'
next(e)
Traceback (most recent call last):
  File "<pyshell#40>", line 1, in <module>
    next(e)
# python从3.8以后字典可以排序
list(d.values())
['70', '105', '115', '104', '67']
list(reversed(d.values()))
['67', '104', '115', '105', '70']

嵌套

#
d =  {"吕布":{"语文":60, "数学":70, "英语":80}, "关羽":{"语文":80, "数学":90, "英语":70}}
d
{'吕布': {'语文': 60, '数学': 70, '英语': 80}, '关羽': {'语文': 80, '数学': 90, '英语': 70}}
# 获取吕布的数学成绩
d["吕布"]["数学"]
70
# 列表。。
d =  {"吕布":[60, 70, 80], "关羽":[80, 90, 70]}
d["吕布"][1]
70

字典推导式

d = dict.fromkeys("FishC")
d.update(F="70", i="105", s="115", h="104", C="67")
d
{'F': '70', 'i': '105', 's': '115', 'h': '104', 'C': '67'}
b = {v:k for k,v in d.items()}
b
{'70': 'F', '105': 'i', '115': 's', '104': 'h', '67': 'C'}
c = {v:k for k,v in d.items() if v > 100}
c
{'105':'i', '115':'s', '104':'h'}

#
d = {x:ord(x) for x in "FishC"}
d
{'F': 70, 'i': 105, 's': 115, 'h': 104, 'C': 67}


# 字典值 可以重新赋值,前边的被覆盖了。每个键被赋值3次,只需要最后一次
# 键值保持唯一映射关系
d = {x:y for x in [1, 3, 5] for y in [2, 4, 6]}
d
{1: 6, 3: 6, 5: 6}
d = {x:y for x in [1, 3, 5] for y in [2, 4, 6, 7]}
d
{1: 7, 3: 7, 5: 7}

集合

# 集合中所有元素都应该是独一无二的,并且是无序的。
type({})
<class 'dict'>
type({"one"})
<class 'set'>
type({"one":1})
<class 'dict'>、

# 创建一个集合通常有三种方法
- 花括号
{"FishC", "Python"}
{'Python', 'FishC'}
- 集合推导式
{s for s in "FishC"}
{'C', 's', 'F', 'i', 'h'}
- set
set("FishC")
{'C', 's', 'F', 'i', 'h'}

# 集合时无序的
s = set("FishC")
s[0]
Traceback (most recent call last):
  File "<pyshell#96>", line 1, in <module>
    s[0]
TypeError: 'set' object is not subscriptable
    
# 判断某个元素是否在这个集合
- in
'C' in s
True
'c' not in s
True
# 访问集合中的元素
for i in s:
    print(i)
    
C
s
F
i
h
# 集合去重
set([1, 1, 3, 4, 5])
{1, 3, 4, 5}
判断列表是否有相同的元素
s = [1, 1, 2, 3, 5]
len(s) == len(set(s))
False

isdisjoint()

- isdisjoint() 判断两个集合是否不相关。
s = set("FishC")
s
{'C', 's', 'F', 'i', 'h'}
s.isdisjoint(set("Python"))
False
s.isdisjoint(set("JAVA"))
True
省略写法
s.isdisjoint("JAVA")
True
s.isdisjoint("Python")
False

issubset() 子集

- issubset() 对于两个集合A,B,如果集合A中任意一个元素都是集合B中的元素,那么就说这两个集合有包含关系,称集合A为集合B的子集。
s = set("FishC")
s
{'C', 's', 'F', 'i', 'h'}
s.issubset("FishC.com.cn")
True

issuoerset() 超集

- issuoerset() 对于两个集合A,B,如果集合B中任意一个元素都是集合A中的元素,那么就说这两个集合有包含关系,称集合A为集合B的超集。
s = set("FishC")
s
{'C', 's', 'F', 'i', 'h'}
s.issuperset("Fish")
True

union() 并集

- union() 对于两个集合A,B,把他们所有的元素并在一起组成的集合,叫做集合A与集合B的并集。
s = set("FishC")
s
{'C', 's', 'F', 'i', 'h'}
s.union({1, 2, 3})
{1, 2, 3, 'C', 's', 'F', 'h', 'i'}
支持多参数
s.union({1, 2, 3},"AA")
{1, 2, 3, 'i', 'h', 'A', 'C', 's', 'F'}

intersection() 交集

- intersection()  对于两个集合A,B,有所有属于集合A且属于集合B的元素所组成的集合,叫做集合A与集合B的交集。
s = set("FishC")
s
{'C', 's', 'F', 'i', 'h'}
s.intersection("Fish")
{'F', 's', 'h', 'i'}
支持多参数
s.intersection("php", "Python")
{'h'}

difference() 差集

 - difference() 对于两个集合A,B,由所有属于集合A且不属于集合B的元素所组成的集合,叫做集合A与集合B的差集。
s
{'C', 's', 'F', 'i', 'h'}
s.difference("Fish")
{'C'}
支持多参数
s.difference("p", "PhP")
{'C', 's', 'F', 'i'}

symmetric_difference() 对称差集 不能多参数

- symmetric_difference 对于两个集合A,B,先排除集合A与集合B的所有共同元素,有剩余的元素组成的集合,叫做集合A与集合B的对称差集。
s
{'C', 's', 'F', 'i', 'h'}
s.symmetric_difference("Python")               
{'C', 's', 'P', 'F', 'y', 'i', 't', 'o', 'n'}

运算符检测

使用运算符 符号两边必须为集合才行@@

s
{'i', 's', 'h', 'C', 'F'}
s <= set("FishC") 子集
True
s < set("FishC") 真子集 去掉=
False
s < set("FishC.com.cn")
True
s > set("FishC.com.cn") 超集
False
s > set("FishC")
False
s >= set("FishC")
True
s | {1, 2, 3} | set("PHP") 并集
{1, 2, 'i', 3, 's', 'h', 'P', 'H', 'C', 'F'}
s & set("Php") & set("Python") 交集
{'h'}
s - set("Php") - set("Python") 差集
{'C', 'i', 'F', 's'}
s ^ set("Python") 对称差集
{'o', 's', 'y', 'P', 'n', 'C', 't', 'i', 'F'}

集合按照可变否,分为可变集合和不可变集合

set() 可变集合

frozenset() 不可变集合

t = frozenset("FishC")
t
frozenset({'i', 's', 'h', 'C', 'F'})

update()

- update(*others) 支持多参数 
other  支持一个参数
others 支持多个参数
定义集合
t = frozenset("FishC")
t
frozenset({'i', 's', 'h', 'C', 'F'})
s = set("FishC")
s
{'i', 's', 'h', 'C', 'F'}
插入元素
s.update([1, 1], "23")
s
{1, 'i', '3', 's', 'h', 'C', 'F', '2'}
t 集合报错
t.update([1, 1], "23")
Traceback (most recent call last):
  File "<pyshell#20>", line 1, in <module>
    t.update([1, 1], "23")
AttributeError: 'frozenset' object has no attribute 'update'
s.intersection_update("FishC")
s
{'F', 'i', 's', 'h'}

s.difference_update("Php", "Python")
s
{'i', 's', 'C', 'F'

s.symmetric_difference_update("Python")
s
{'i', 'o', 's', 'y', 'h', 'P', 'C', 'n', 'F', 't'}

add() 加入元素

- add() 传入的字符串 就加入整个字符串
update 是将字符串的每个字符当做一个元素加入,迭代。
s
{'i', 'o', 's', 'y', 'h', 'P', 'C', 'n', 'F', 't'}
s.add("45")
s
{'i', 'o', '45', 's', 'y', 'h', 'P', 'C', 'n', 'F', 't'}

remove(elem) discard(elem) 删除元素

区别: 指定的元素不存在,remove会抛出异常,而discard则静默处理。

- remove(elem)  discard(elem) 删除元素
s.remove("HH")
Traceback (most recent call last):
  File "<pyshell#37>", line 1, in <module>
    s.remove("HH")
KeyError: 'HH'
s.discard("HH")

pop() 删除 随机从集合中弹出一个元素

- pop()  删除 随机从集合中弹出一个元素
s.pop()
'i'
s.pop()
'o'
s.pop()
'45'
s
{'s', 'y', 'h', 'P', 'C', 'n', 'F', 't'}

clear() 清空集合

- clear() 清空集合
s.clear()
s
set()

可哈希

hash(object) 获取一个对象的哈希值

对整数 他的哈希值不变。
如果两个对象的值是相等的,那么他们哈希值也相等。整数 浮点数
hash(1)
1
hash(1.0)
1
hash(1.001)
2305843009213441
hash("FishC")
-8974866538340790805
hash([1, 2, 3]) 列表可变,哈希不行
Traceback (most recent call last):
  File "<pyshell#1>", line 1, in <module>
    hash([1, 2, 3])
TypeError: unhashable type: 'list'
hash((1, 2, 3))
529344067295497451

# 只有可哈希的元素才能作为 字典的键 以及集合的元素。
{"Python":520, "FishC":1314}
{'Python': 520, 'FishC': 1314}
{[1, 2, 3]:520}
Traceback (most recent call last):
  File "<pyshell#6>", line 1, in <module>
    {[1, 2, 3]:520}
TypeError: unhashable type: 'list'
        
{"Python", 520, "FishC", 1314}
{520, 1314, 'FishC', 'Python'}

{"Python", 520, "FishC", 1314, [1, 2, 4]}
Traceback (most recent call last):
  File "<pyshell#8>", line 1, in <module>
    {"Python", 520, "FishC", 1314, [1, 2, 4]}
TypeError: unhashable type: 'list'

嵌套集合

x = {1, 2, 3}
y = {x, 4, 5}
Traceback (most recent call last):
  File "<pyshell#10>", line 1, in <module>
    y = {x, 4, 5}
TypeError: unhashable type: 'set'
因为集合它是一个可变容器。而可变的容器则是不可哈希的。

可以使用frozenset不可变集合嵌套
x = frozenset(x)
y = {x, 4, 5}
y
{frozenset({1, 2, 3}), 4, 5}

函数

函数打包代码,最大程度的实现代码的重用,减少冗余的代码。将不同的代码进行封装,分解,从而降低结构的复杂度,提高代码的可读性。

内置(BIF)函数:print(), input(),sorted()...... build-in function

创建和调用函数:

定义函数:
def myfunc():
    pass # pass 占位符

调用函数:
myfunc()


def myfunc():
    for i in range(3):
        print("I love you")
        
myfunc()
I love you
I love you
I love you
# 函数的参数
f是表明是f字符串,然后替换name字段。format格式化,可以把变量替换。
def myfunc(name):
    for i in range(3):
        print(f"I love {name}.")     
myfunc("Python")
I love Python.
I love Python.
I love Python.

def myfunc(name, times):
    for i in range(times):
        print(f"I love {name}.")     
myfunc("Python", 2)
I love Python.
I love Python.
函数的参数 分为形式参数 和 实际参数两种,比如name times为形参,传入的 Python 2 为实参。

# 函数的返回值
def div(x, y):
    z = x / y
    return z
div(4, 2)
2.0
可以这样写:
def div(x, y):
    return x / y
div(4, 2)
2.0
# 条件判断:
def div(x, y):
    if y == 0:
        return "除数不能为0!"
    else:
        return x / y

div(4, 0)
'除数不能为0!'
div(4, 2)
2.0
# 不指定返回值,默认返回none
def myfunc():
    pass
print(myfunc())
None

位置参数

关键字参数
# --
def myfunc(s, vt, o):
    return "".join((o, vt, s))

myfunc("我", "打了", "小甲鱼")
'小甲鱼打了我'
myfunc("小甲鱼", "打了", "我")
'我打了小甲鱼'
-- 关键字参数 参数太多可以直接指定
myfunc(o="我", vt="打了", s="小甲鱼")
'我打了小甲鱼'
# 注意 如果指定不是全部关键字,则位置参数必须在关键字参数之前。
myfunc(o="我", "打了", "小甲鱼")
SyntaxError: positional argument follows keyword argument
myfunc(s="我", "打了", "小甲鱼")
SyntaxError: positional argument follows keyword argument
myfunc("我", "打了", o="小甲鱼") # 位置参数在关键字参数之前
'小甲鱼打了我'
默认参数
-- 默认参数 
函数在定义的时候可以指定默认值,若没有传入实参,那么就采用默认值代替。
def myfunc(s, vt, o="小甲鱼"):
    return "".join((o, vt, s))
myfunc("香蕉", "吃")
'小甲鱼吃香蕉'
myfunc("香蕉", "吃", "嘿嘿")
'嘿嘿吃香蕉'
# 使用默认参数应该放在最后。不然报错。默认参数=关键字参数
def myfunc(s="苹果", vt, o="小甲鱼"):
    return "".join((o, vt, s))
SyntaxError: non-default argument follows default argument
def myfunc(vt,s="苹果", o="小甲鱼"):
    return "".join((o, vt, s))
myfunc("香蕉")
'小甲鱼香蕉苹果'
myfunc("chi", s="栗子", o="我")
'我chi栗子'

# 冷知识 help()
/ 左侧是不能使用关键字参数的
help(abs)
Help on built-in function abs in module builtins:
abs(x, /)
    Return the absolute value of the argument.

help(sum)
Help on built-in function sum in module builtins:
sum(iterable, /, start=0)
    Return the sum of a 'start' value (default: 0) plus an iterable of numbers
/ 左侧是不能使用关键字参数的 只能使用位置参数去传递。
abs(-1.5)
1.5
abs(x = -1.5)
Traceback (most recent call last):
  File "<pyshell#36>", line 1, in <module>
    abs(x = -1.5)
TypeError: abs() takes no keyword arguments
 /左侧不能用关键字参数。右侧可以。
sum([1, 2, 3], 4)
10
sum([1, 2, 3], start=4)
10
- 例子:/左侧不能用关键字参数。右侧可以。
def abc(a, /, b, c):
    print(a, b, c)
abc(1, 2, 3)
1 2 3
abc(a=1, 2, 3)
SyntaxError: positional argument follows keyword argument
abc(1, b=2, c=3)
1 2 3

#  * 号使用位置参数报错:
- *号后边的必须使用关键字参数。
def abc(a, *, b, c):
    print(a, b, c)
abc(1, 2, 3)
Traceback (most recent call last):
  File "<pyshell#50>", line 1, in <module>
    abc(1, 2, 3)
TypeError: abc() takes 1 positional argument but 3 were given
abc(1, b=2, c=3)
1 2 3
abc(a=1, b=2, c=3)
1 2 3
收集参数:
-- 收集参数 *args 多个参数
print("嘿嘿", "爱", "编程")
嘿嘿 爱 编程
# 收集参数 *args 多个参数
def myfunc(*args):
    print("有{}个参数。".format(len(args)))
    print("第二个参数是:{}".format(args[1]))

myfunc(1, 2, 3, 4, 5)
有5个参数。
第二个参数是:2
myfunc("小甲鱼", "Pyhon")
有2个参数。
第二个参数是:Pyhon
# 原理 元组的打包和解包
通过*号 将参数打包到元组里。
def myfunc(*args):
    print(args)
myfunc(1, 2, 3, 4, 5)
(1, 2, 3, 4, 5)

def myfunc():
    return 1, 2, 3
myfunc()
(1, 2, 3)
x, y, z = myfunc()
x
1
y
2
z
3
def myfunc(*args):
    print(type(args))   
myfunc(1, 2, 3)
<class 'tuple'>

# 如果在收集参数后边还需要指定其他参数,那么在调用的时候,则需要关键字参数。否则python就会把实参纳入到收集参数中。
def myfunc(*args, a, b):
    print(args, a, b)
myfunc(1, 2, 3, 4, 5)
Traceback (most recent call last):
  File "<pyshell#79>", line 1, in <module>
    myfunc(1, 2, 3, 4, 5)
TypeError: myfunc() missing 2 required keyword-only arguments: 'a' and 'b' 
myfunc(1, 2, 3, a=4, b=5)
(1, 2, 3) 4 5

# 打包成字典
**kwargs 用两个星号表示。在调用时候必须使用关键字参数了。
def myfunc(**kwargs):
    print(kwargs)

myfunc(a=1, b=2, c=3)
{'a': 1, 'b': 2, 'c': 3}

# 混合模式
def myfunc(a, *b, **c):
    print(a, b, c)
myfunc(1, 2, 3, 4, x=5, y=6)
1 (2, 3, 4) {'x': 5, 'y': 6}

# format参数 *args, **kwargs也是
help(str.format)
Help on method_descriptor:

format(...)
    S.format(*args, **kwargs) -> str
    
    Return a formatted version of S, using substitutions from args and kwargs.
    The substitutions are identified by braces ('{' and '}').


# 解包参数
args = (1, 2, 3, 4)
def myfunc(a, b, c, d):
    print(a, b, c, d)
直接args报错,   
myfunc(args)
Traceback (most recent call last):
  File "<pyshell#105>", line 1, in <module>
    myfunc(args)
TypeError: myfunc() missing 3 required positional arguments: 'b', 'c', and 'd'
        
myfunc(*args) # *args 解包出关键字参数
1 2 3 4

kwargs = {'a':1, 'b':2, 'c':3, 'd':4} # 同上
myfunc(**kwargs)
1 2 3 4
作用域

局部作用域

def myfunc():
    x = 520
    print(x)

    
myfunc()
520
外部调用报错:
print(x)
Traceback (most recent call last):
  File "<pyshell#5>", line 1, in <module>
    print(x)
NameError: name 'x' is not defined

x = 880
def myfunc():
    print(x) 
myfunc()
880
print(x)
880
def myfunc():
    x = 520
    print(x)
myfunc()
520
局部变量会覆盖同名的全局变量。
# id值 判断变量
x = 880
id(x)
1509452130864
def myfunc():
    print(id(x))
myfunc()
1509452130864

def myfunc():
    x = 520
    print(id(x))
myfunc()
1509452133296

global 语句

# 在函数中使用global,要注意,,,
x = 880
def myfunc():
    global x
    x = 520
    print(x)

myfunc()
520
print(x)
520

嵌套函数

--
里边函数无法直接调用:
def funA():
    x = 520
    def funB():
        x = 880
        print("In funB, x=", x)
    print("In funA, x=", x) 
funB()
Traceback (most recent call last):
  File "<pyshell#45>", line 1, in <module>
    funB()
NameError: name 'funB' is not defined. Did you mean: 'funA'?
# 调用 funA也没调用funB。        
funA()
In funA, x= 520

# 重新定义:
def funA():
    x = 520
    def funB():
        x = 880
        print("In funB, x=", x)
    funB() # 在funA中调用funB。
    print("In funA, x=", x)

funA()
In funB, x= 880
In funA, x= 520

nonlocal语句

-- 在内部函数去修改外部函数的变量。
nonlocal是修改上一层嵌套的函数变量,若有多层嵌套也只修改上一层,上一层没有则报错。
global是修改函数体外的全局变量。
def funA():
    x = 520
    def funB():
        nonlocal x # 内部函数中声明 x
        x = 880
        print("In funB, x=", x)
    funB()
    print("In funA, x=", x)

    
funA()
In funB, x= 880
In funA, x= 880

LEGB 规则

LEGB : L > E > G > B
L = local 指局部作用域
E = Enclosed 是嵌套函数的外层函数作用域
G = Global 是全局作用域
B = Builb-In 是内置作用域

当局部作用和全局作用域发生冲突的时候,使用局部作用域的变量,除非使用global语句进行特别声明。
当函数嵌套发生的时候,局部作用域会覆盖外层函数的作用域,除非使用nonlocal语句进行声明。

build-in:
str(520)
'520'
str = "小甲鱼把str给毁了" # 升级为全局变量名称(把函数当场变量给赋值了)
str(520)
Traceback (most recent call last):
  File "<pyshell#56>", line 1, in <module>
    str(520)
TypeError: 'str' object is not callable
- 复原 del
del(str)
str(520)
'520'
闭包
-- closure闭包
def funA():
    x = 880
    def funB():
        print(x)
    funB()
    
funA()
880
# 不通过调用funA函数直接调用funB函数
def funA():
    x = 880
    def funB():
        print(x)
    return funB # 将funB作为返回值,返回
funA()
<function funA.<locals>.funB at 0x0000015F72726A70>
funA()()
880
funny = funA()
funny()
880
#  嵌套函数作用域 会被保留。
LEGB : L > E > G > B
L = local 指局部作用域
E = Enclosed 是嵌套函数的外层函数作用域
G = Global 是全局作用域
B = Builb-In 是内置作用域

def power(exp):
    def exp_of(base):
        return base ** exp
    return exp_of

square = power(2)
cube = power(3)
square(2)
4
square(5)
25
cube(2)
8
cube(5)
125

# nonloal 
def outer():
    x = 0
    y = 0
    def inner(x1, y1):
        nonlocal x, y
        x += x1
        y += y1
        print(f"现在,x = {x}, y = {y}")
    return inner

move = outer()
move(1, 2)
现在,x = 1, y = 2
move(-2, 2) # 注意这里是 根据上个move的值,去计算的,带记忆功能的move。
现在,x = -1, y = 4

# x y轴移动
origin = (0, 0)        # 这个是原点
legal_x = [-100, 100]  # 限定x轴的移动范围
legal_y = [-100, 100]  # 限定y轴的移动范围

def create(pos_x=0, pos_y=0):
    def moving(direction, step):
        nonlocal pos_x, pos_y
        new_x = pos_x + direction[0] * step
        new_y = pos_y + direction[1] * step

        if new_x < legal_x[0]:
            pos_x = legal_x[0] - (new_x - legal_x[0])
        elif new_x > legal_x[1]:
            pos_x = legal_x[1] - (new_x - legal_x[1])
        else:
            pos_x = new_x
            
        if new_y < legal_y[0]:
            pos_y = legal_y[0] - (new_y - legal_y[0])
        elif new_y > legal_y[1]:
            pos_y = legal_y[1] - (new_y - legal_y[1])
        else:
            pos_y = new_y

        return pos_x, pos_y

    return moving

# 执行:
====================== RESTART: D:/Python/xuexiPY/bibao.py =====================
move = create()
print("向右移动20步后,位置是:", move([1, 0], 20))
向右移动20步后,位置是: (20, 0)
print("向上移动120步后,位置是:", move([0, 1], 120))
向上移动120步后,位置是: (20, 80)
print("向右下角移动88步后,位置是:", move([1, -1], 88))
向右下角移动88步后,位置是: (92, -8)

闭包函数:
1. 利用嵌套函数的外层作用域具有记忆能力这个特性,让数据保存在外层函数的参数或者变量中。
2. 将内层函数作为返回值给返回,这样就可以从外部间接调用到内层的函数
装饰器:
开胃菜:
把一个函数作为参数传递给另一个函数

- 调用函数
def myfunc():
    print("正在调用myfunc...")  
def report(func):
    print("主人,我要开始调用函数了...")
    func()
    print("主人,我调用完函数啦。。。")
report(myfunc)
主人,我要开始调用函数了...
正在调用myfunc...
主人,我调用完函数啦。。。

#例子
import time
def time_master(func):
    print("开始运行程序...")
    start = time.time()
    func()
    stop = time.time()
    print("结束程序运行...")
    print(f"一共耗费了 {(stop-start):.2f} 秒")

def myfunc():
    time.sleep(2)
    print("Hello world")

time_master(myfunc)
开始运行程序...
Hello world
结束程序运行...
一共耗费了 2.06 秒

# 上正菜!!
发现并没有运行time_master,就执行了
实际是闭包
import time

def time_master(func):
    def call_func():
        print("开始运行程序...")
        start = time.time()
        func()
        stop = time.time()
        print("结束程序运行...")
        print(f"一共耗费了 {(stop-start):.2f} 秒")
    return call_func

@time_master # 装饰器 语法糖,放在要装饰的函数前   
def myfunc():
    time.sleep(2)
    print("Hello world")

myfunc()
# 运行:
=================== RESTART: D:/Python/xuexiPY/zhuangshiqi.py ==================
开始运行程序...
Hello world
结束程序运行...
一共耗费了 2.01 秒

# 多个装饰器 用在同一个函数上。
装饰器按靠近函数的顺序执行,执行顺序 square > cube > add. 
def add(func):
    def inner():
        x = func()
        return x + 1
    return inner

def cube(func):
    def inner():
        x = func()
        return x * x * x
    return inner

def square(func):
    def inner():
        x = func()
        return x * x
    return inner

#装饰器按靠近函数的顺序执行,执行顺序 square > cube > add.
@add
@cube
@square  
def test():
    return 2

print(test())
# 结果:
================ RESTART: D:/Python/xuexiPY/zhuangshiqi_more.py ================
65

# 给装饰器传递参数
import time
def logger(msg):
    def time_master(func):
        def call_func():
            start = time.time()
            func()
            stop = time.time()
            print(f"[{msg}]一共耗费了{(stop-start):.2f}")
        return call_func
    return time_master

@logger(msg="A")
def funA():
    time.sleep(1)
    print("正在调用funA...")

@logger(msg="B")
def funB():
    time.sleep(1)
    print("正在调用funB...")

funA()
funB()
# 结果
==================== RESTART: D:/Python/zhuangshiqi_most.py ====================
正在调用funA...
[A]一共耗费了1.03
正在调用funB...
[B]一共耗费了1.02
lambda表达式
-- lambda 一行流表达式 匿名函数
lambda是个表达式而非语句,他可以出现在python语法不允许def出现的地方。这个是最大的优势。希望lambda去做一些简单的事情。

lambda arg1, arg2, arg3, ... argN : expression
# 普通函数
def square(x):
    return x * x
square(2)
4
# lambda表达式
squareX = lambda y : y * y
squareX(2)
4

square
<function square at 0x000001F97A2EE290>
squareX
<function <lambda> at 0x000001F97A3A6200>
# lambda 在列表中 成为一个元素
y = [lambda x : x * x, 2, 3]
y[0](y[1]) # 调用lambda,传入y列表第二个参数
4
# 传递给map函数
mapped = map(lambda x : ord(x) + 10, "FishC")
list(mapped)
[80, 115, 125, 114, 77]
普通写法:
def boring(x):
    return ord(x) + 10

list(map(boring, "FishC"))
[80, 115, 125, 114, 77]

# 10以内的奇数
list(filter(lambda x : x % 2, range(10)))
[1, 3, 5, 7, 9]
生成器
yield -- generator生成器
# 定义生成器
def counter():
    i = 0
    while i < 5:
        yield i # 定义生成器
        i += 1     
counter()
<generator object counter at 0x000001F97A36D540>
# 调用生成器counter
for i in counter():
    print(i)
  
0
1
2
3
4
# 使用next函数
c = counter()
c
<generator object counter at 0x000001F97A36E030>
next(c)
0
next(c)
1
next(c)
2
next(c)
3
next(c)
4
next(c)
Traceback (most recent call last):
  File "<pyshell#44>", line 1, in <module>
    next(c)
StopIteration
# 不支持下标索引方法
c = counter()
c[2]
Traceback (most recent call last):
  File "<pyshell#46>", line 1, in <module>
    c[2]
TypeError: 'generator' object is not subscriptable
    
# 求出斐波那契数列
def fib():
    back1, back2 = 0, 1
    while True:
        yield back1
        back1, back2 = back2, back1 + back2
  
f = fib()
next(f)
0
next(f)
1
next(f)
1
next(f)
2
next(f)
3
next(f)
5
next(f)
8
# 生成器表达式
(i ** 2 for i in range(10))
<generator object <genexpr> at 0x000001F97A3D85F0>
list(i ** 2 for i in range(10))
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
t = (i ** 2 for i in range(10))
next(t)
0
next(t)
1
next(t)
4
next(t)
9
for i in t:
    print(i)

    
16
25
36
49
64
81
生成器的两种表达方法:
1. 使用函数利用 yield 表示
2. 使用生成器表达式
递归
递归就是函数调用自身的过程
# 递归
错误示范:疯狂调用自己。
def funC():
    print("我被调用了")
    funC()
funC()
我被调用了
我被调用了
我被调用了
我被调用了
我被调用了
我被调用了
我被调用了。。。
# 改一下:加上条件判断语句 让递归失控局面得到控制
def funC(i):
    if i > 0:
        print("我被调用了")
        i -= 1
        funC(i)
 
funC(3)
我被调用了
我被调用了
我被调用了
# 注意!:
递归正常工作,必须要有一个结束条件,并且每次调用都会向着这个结束条件去推进。

# 举例 
求一个数的阶乘!,5的阶乘=1 * 2 * 3 * 4 * 5
1. 迭代方式
def diedai(n):
    result = n
    for i in range(1, n):
        result *= i
    return result

diedai(5)
120
diedai(10)
3628800

2. 递归方式
def digui(n):
    if n == 1:
        return 1
    else:
        return n * digui(n-1)

digui(5)
120
digui(10)
3628800

-- 求出斐波那契数列
1. 迭代方式
def fib(n):
    a = 1
    b = 1
    c = 1
    while n > 2:
        c = a + b
        a = b
        b = c
        n -= 1
    return c

fib(12)
144
2. 递归方式
def dg(n):
    if n ==1 or n == 2:
        return 1
    else:
        return dg(n-1) + dg(n-2)
    
dg(12)
144

# 效率问题
dg(120) # 要很久。。
Traceback (most recent call last):
  File "<pyshell#151>", line 1, in <module>
    dg(120)
  File "<pyshell#148>", line 5, in dg
    return dg(n-1) + dg(n-2)
  File "<pyshell#148>", line 5, in dg
    return dg(n-1) + dg(n-2)
  File "<pyshell#148>", line 5, in dg
    return dg(n-1) + dg(n-2)
  [Previous line repeated 103 more times]
  File "<pyshell#148>", line 1, in dg
    def dg(n):
KeyboardInterrupt
fib(120) # 迭代快u
5358359254990966640871840

汉诺塔
-- 递归
'''
def hanoi(n, x, y, z):
    if n == 1:
        print(x, '-->', z) #
    else:
        hanoi(n-1, x, z, y) #
        print(x, '-->', z)  #
        hanoi(n-1, y, x, z) #

n = int(input('请输入汉诺塔的层数:'))
hanoi(n, 'A', 'B', 'C')

'''
#'''
def hannuota(n, a, b, c):
    if n == 1:
        print(a, '-->', c)  # n 为盘子,n=1 直接塔1拿到塔3
    else:
        hannuota(n-1, a, c, b) # n!=1, n-1盘子通过塔3移到塔2
        print(a, '-->', c)     # 剩余一个直接从塔1拿到塔3 
        hannuota(n-1, b, a, c) # 最后塔2通过塔1,移到塔3

hannuota(3, "塔1", "塔2", "塔3")


#'''


函数文档
-- 函数文档,注释一定是在函数的最顶部的。
# 定义一个函数文档
def exchange(dollar, rate=6.32):
    """
    功能:汇率转换,美元 -> 人民币
    参数:
    - dollar 美元数量
    - rate 汇率, 默认值是 6.32 (2022-05-26)
    返回值:
    - 人民币的数量
    """
    return dollar * rate

exchange(20)
126.4
#查看函数文档
help(exchange)
Help on function exchange in module __main__:

exchange(dollar, rate=6.32)
    功能:汇率转换,美元 -> 人民币
    参数:
    - dollar 美元数量
    - rate 汇率, 默认值是 6.32 (2022-05-26)
    返回值:
    - 人民币的数量
    

类型注释
-- 类型注释:
# 希望 表示s是字符串类型,n是整数类型参数传入,最后函数返回 字符串类型的返回值。 
def times(s:str, n:int) -> str:
    return s * n

times("FishC", 5)
'FishCFishCFishCFishCFishC'
# 类型注释是给人看的,不是给机器看的,传入不一样的:也OK
times(5, "FC")
'FCFCFCFCFC'
times(5, 5)
25
# 设置默认参数
def times(s:str = "FishC", n:int = 3) -> str:
    return s * n
times()
'FishCFishCFishC'

def times(s:list, n:int = 3) -> list:
    return s * n
times([1, 2, 3])
[1, 2, 3, 1, 2, 3, 1, 2, 3]

-- 期望list列表中元素是整数类型,返回list类型值:
def times(s:list[int], n:int = 3) -> list:
    return s * n
-- 字典key为str类型,value为int类型。返回值为list类型。
def times(s:dict[str, int], n:int = 3) -> list:
    return list(s.keys()) * n
times({'A':1, 'B':2, 'C':3})
['A', 'B', 'C', 'A', 'B', 'C', 'A', 'B', 'C']
内省
-- 内省
def times(s:dict[str, int], n:int = 3) -> list:
    return list(s.keys()) * n
# 程序运行的时候获取函数的名字	
times.__name__
'times'
# annotations 查看传入的类型注释:
times.__annotations__
{'s': dict[str, int], 'n': <class 'int'>, 'return': <class 'list'>}
# doc 查看函数文档:
exchange.__doc__
'\n    功能:汇率转换,美元 -> 人民币\n    参数:\n    - dollar 美元数量\n    - rate 汇率, 默认值是 6.32 (2022-05-26)\n    返回值:\n    - 人民币的数量\n    '
print(exchange.__doc__)
    功能:汇率转换,美元 -> 人民币
    参数:
    - dollar 美元数量
    - rate 汇率, 默认值是 6.32 (2022-05-26)
    返回值:
    - 人民币的数量

高阶函数
-- 可以接收另外一个函数当做参数的函数,叫高阶函数。
装饰器 map filter min max salty等都是高阶函数, 他们的key接收的是一个函数对象。
模块:functools 包含非常多高阶函数以及装饰器。
# reduce函数,第一个参数是指定一个函数,这个函数必须是指定两个参数,第二个参数是可迭代对象。reduce将可迭代对象中的元素依次传递到第一个参数指定的函数中。最终返回累计的结果。 
def add(x, y):
    return x + y

import functools
functools.reduce(add, [1, 2, 3, 4, 5])
15
-- 等于:
add(add(add(add(1, 2), 3), 4), 5)
15
计算10的阶乘,结合lambda
functools.reduce(lambda x,y:x*y, range(1, 11))
3628800

# 偏函数
--  偏函数是指对指定的函数进行二次包装,通常是将现有的函数部分参数预先给绑定,从而得到一个新的函数。就称之为偏函数。
#
square = functools.partial(pow, exp=2)
square(2)
4
square(3)
9
cube = functools.partial(pow, exp=3)
cube(2)
8
cube(3)
27

# @wraps 装饰装饰器
=================== RESTART: D:\Python\xuexiPY\zhuangshiqi.py ==================
开始运行程序...
Hello world
结束程序运行...
一共耗费了 2.02 秒
myfunc.__name__
'call_func'

=================== RESTART: D:\Python\xuexiPY\zhuangshiqi.py ==================
开始运行程序...
Hello world
结束程序运行...
一共耗费了 2.05 秒
myfunc.__name__
'myfunc'
# 代码
import time
import functools # 引入functools模块 1
def time_master(func):
    @functools.wraps(func) # 在调用的函数前 加入 2
    def call_func():
        print("开始运行程序...")
        start = time.time()
        func()
        stop = time.time()
        print("结束程序运行...")
        print(f"一共耗费了 {(stop-start):.2f} 秒")
    return call_func

@time_master    
def myfunc():
    time.sleep(2)
    print("Hello world")

myfunc()

永久存储

操作文件

-- py中文件的创建读取等操作
# open("文件路径和名字,没有则创建", "操作权限")
f = open("FishC.txt", "w")
f.write("I love Python") # 写入 会覆盖。。
13
f.writelines(["I love KOBE.\n", "I love my wife."]) #  写入多行
f.close() # close 保存文件

f = open("FishC.txt", "r+") # r+ 可读可写模式
f.readable() # readable判断文件是否可读,返回布尔值
True
f.writable() # writable判断文件是否可写,返回布尔值
True
for i in f:
    print(i)

    
I love PythonI love KOBE.

I love my wife.
# read 从文件对象中读取指定数量的字符(EOF停止),当未指定该参数,或者该参数为负数值得时候,读取剩余所有字符串。
f.read() # 上边print遍历f文件所有字符了,所以read为空
''
f.tell() #返回当前文件指针在文件对象中的位置
42
# 重新指定文件指针位置:
f.seek(0)
0
f.readline() # readline每次读取一行
'I love PythonI love KOBE.\n'
f.read() # 读取剩余的文件字符。
'I love my wife.'
# 不使用close关闭文件,保存文件
f.write("I love my wifi.")
15
f.flush() # 不一定有效。这次有效了
f.read()
''
f.tell()
57
f.seek(0)
0
f.read()
'I love PythonI love KOBE.\nI love my wife.I love my wifi.'
# 截断操作 指定的是保留的字符个数!
f.truncate(26)
26
f.seek(0)
0
f.read()
'I love PythonI love KOBE.\n'
# 截断操作 注意!坑
单独的写入模式 即 “w” 
f = open("FishC.txt", "w") # 打开
f.close() # 直接关闭。文件内容就没了。。

image-20220527152607007

路径处理

-- 以下操作都需要引入Path 模块
from pathlib import Path
-- 
from pathlib import Path
# 获取当前目录的路径 cwd()
Path.cwd()
WindowsPath('D:/Python')
p = Path('D:/Python')
p
WindowsPath('D:/Python')
/ 进行拼接文件名
q = p / "FishC.txt"
q
WindowsPath('D:/Python/FishC.txt')
判断路径
# is_dir() 判断一个路径是否是个文件夹
p.is_dir()
True
q.is_dir()
False
# if_file() 判断一个路径是否为一个文件
q.is_file()
True
p.is_file()
False
# exists()检测一个路径是否存在
p.exists()
True
q.exists()
True
Path("C:/404").exists()
False
获取操作
# name 获取路径的最后一个部分
p.name
'Python'
q.name
'FishC.txt'
Path.cwd().name
'Python'
(Path.cwd() / "FishC.txt").name
'FishC.txt'

# stem 获取文件名
q.stem
'FishC'
p.stem
'Python'

# suffix 获取文件后缀
q.suffix
'.txt'
p.suffix
''
# parent 获取父级目录
q.parent
WindowsPath('D:/Python')
p.parent
WindowsPath('D:/')

# parents 获取逻辑祖先路径构成的序列
q.parents
<WindowsPath.parents>
ps = q.parents
for i in ps:
    print(i)

D:\Python
D:\
支持索引:
ps[0]
WindowsPath('D:/Python')
ps[1]
WindowsPath('D:/')

# parts 将路径的各个组件拆分成元组
p.parts
('D:\\', 'Python')
q.parts
('D:\\', 'Python', 'FishC.txt')

# stat() 查询文件或文件夹的信息
p.stat()
os.stat_result(st_mode=16895, st_ino=47006321110694543, st_dev=258282061, st_nlink=1, st_uid=0, st_gid=0, st_size=4096, st_atime=1653636946, st_mtime=1653636934, st_ctime=1619356712)
p.stat().st_size
4096
q.stat().st_size
0

# 相对路径 绝对路径
q p都是绝对路径。从开头到结尾

# resolve() 将相对路径 转换为绝对路径
Path("./doc").resolve()
WindowsPath('D:/Python/Doc')

# iterdir() 获取当前路径下所有子文件和子文件夹 
-- 需要是文件夹!!
p.iterdir()
<generator object Path.iterdir at 0x000001BEEB882490>
for i in p.iterdir():
    print(i)
 
D:\Python\DLLs
D:\Python\Doc
D:\Python\FishC.txt
D:\Python\include
D:\Python\Lib
D:\Python\libs
D:\Python\LICENSE.txt
D:\Python\NEWS.txt
D:\Python\python.exe
D:\Python\python3.dll
D:\Python\python310.dll
D:\Python\Python36
D:\Python\pythonw.exe
D:\Python\Scripts
D:\Python\tcl
D:\Python\Tools
D:\Python\vcruntime140.dll
D:\Python\vcruntime140_1.dll
D:\Python\xuexiPY
    
# 获取当前路径下的所有文件。file
[x for x in p.iterdir() if x.is_file()]
[WindowsPath('D:/Python/FishC.txt'), WindowsPath('D:/Python/LICENSE.txt'), WindowsPath('D:/Python/NEWS.txt'), WindowsPath('D:/Python/python.exe'), WindowsPath('D:/Python/python3.dll'), WindowsPath('D:/Python/python310.dll'), WindowsPath('D:/Python/pythonw.exe'), WindowsPath('D:/Python/vcruntime140.dll'), WindowsPath('D:/Python/vcruntime140_1.dll')]
增删改查
# mkdir 创建新的文件夹
n = p / "FishC"
n.mkdir()
n.is_dir()
True
n.mkdir() # 存在的文件夹 再创建会报错。
Traceback (most recent call last):
  File "<pyshell#139>", line 1, in <module>
    n.mkdir()
  File "D:\Python\lib\pathlib.py", line 1173, in mkdir
    self._accessor.mkdir(self, mode)
FileExistsError: [WinError 183] 当文件已存在时,无法创建该文件。: 'D:\\Python\\FishC'
- exist_ok=True 忽略报错信息:
n.mkdir(exist_ok=True) 
# 创建多级不存在的目录
n = p / "FishC/A/B/C"
n.mkdir()
Traceback (most recent call last):
  File "<pyshell#142>", line 1, in <module>
    n.mkdir()
  File "D:\Python\lib\pathlib.py", line 1173, in mkdir
    self._accessor.mkdir(self, mode)
FileNotFoundError: [WinError 3] 系统找不到指定的路径。: 'D:\\Python\\FishC\\A\\B\\C'
- parents=True,创建多级目录。
n.mkdir(parents=True, exist_ok=True)
n.is_dir()
True
n
WindowsPath('D:/Python/FishC/A/B/C')

# open()  打开文件
- Path中的open与open类似,只是不需要写“路径”了
n = n / "FishC.txt"
n
WindowsPath('D:/Python/FishC/A/B/C/FishC.txt')
f = n.open("w")
f.write("I love Python")
13
f.close()
# rename() 修改文件或文件夹名字
n.rename("NEWFishC.txt")
WindowsPath('NEWFishC.txt')
改完名字后同时发现文件移动到cwd目录下了,因为没指定路径。
# replace() 替换指定的文件或文件夹
m = Path("NEWFishC.txt")
m
WindowsPath('NEWFishC.txt')
n
WindowsPath('D:/Python/FishC/A/B/C/FishC.txt')
m.replace(n)
WindowsPath('D:/Python/FishC/A/B/C/FishC.txt')
结果m下的NEWFishC.txt移动到n的路径下并且名字改为FishC.txt了

# rmdir()  删除文件夹 
# unlink() 删除文件
n.parent.rmdir() # 非空目录不能删除
Traceback (most recent call last):
  File "<pyshell#160>", line 1, in <module>
    n.parent.rmdir()
  File "D:\Python\lib\pathlib.py", line 1213, in rmdir
    self._accessor.rmdir(self)
OSError: [WinError 145] 目录不是空的。: 'D:\\Python\\FishC\\A\\B\\C'
n
WindowsPath('D:/Python/FishC/A/B/C/FishC.txt')
n.parent
WindowsPath('D:/Python/FishC/A/B/C')
n.unlink() # 删除文件FishC.txt
n.parent.rmdir()


# glob() 功能强大的查找功能
p = Path(".") # 指定目录
p.glob("*.txt") # 查找以.txt结尾的文件
<generator object Path.glob at 0x000001BEEB7DD540>
list(p.glob("*.txt"))
[WindowsPath('FishC.txt'), WindowsPath('LICENSE.txt'), WindowsPath('NEWS.txt')]
# 查找当前目录下的下一级目录中的所有以.py结尾的文件
list(p.glob("*/*.py"))
[WindowsPath('Lib/abc.py'), WindowsPath('Lib/aifc.py'),]
# 查找当前目录下以及下一级目录中的所有以.py结尾的文件
list(p.glob("**/*.py"))
Squeezed text (3360 lines).


with语句

with语句和上下文管理器

为文件操作提供了更为优雅的实现方式

# 
常规:打开文件 操作文件 关闭文件
f = open("FishC.txt", "w")
f.write("I love Python")
13
f.close()
上下文管理:不需要关闭文件
with open("FishC.txt", "w") as f:
    f.write("I love Python")

    
13

pickle

pickle模块 Python对象序列化的第一人,解决永久存储Python对象的问题,允许将字符串、列表、字典这些对象给保存为文件的形式。

# pickle_dump.py 
-- 将对象转换为二进制字节流
import pickle

x, y, z = 1, 2, 3
s = "FishC"
l = ["小甲鱼", 520, 3.14]
d = {"one":1, "two":2}

with open("data.pkl", "wb") as f: #是 wb 注意! 
    pickle.dump(x, f)
    pickle.dump(y, f)
    pickle.dump(z, f)
    pickle.dump(s, f)
    pickle.dump(l, f)
    pickle.dump(d, f)
# 可以写为: pickle.dump((x, y, z, s, l, d), f)
运行生成.pkl二进制文件。

#  pickle.load.py
--  将二进制字节流文件转换为py对象
import pickle

with open("data.pkl", "rb") as f: #是 rb 注意!
    x = pickle.load(f)
    y = pickle.load(f)
    z = pickle.load(f)
    s = pickle.load(f)
    l = pickle.load(f)
    d = pickle.load(f)
# 可以写为:x, y, z, s, l, d = pickle.load(f)
print(x, y, z, s, l, d, sep="\n")
运行:
=================== RESTART: D:\Python\xuexiPY\pickle_load.py ==================
1
2
3
FishC
['小甲鱼', 520, 3.14]
{'one': 1, 'two': 2}

异常

异常exception

  • 语法错误,不按照Python规定的语法来写代码

处理异常

try-except
try-except语句 捕获并处理异常
-- 语法:
try:
    检测范围
except [expression [as identifier]]:
    异常处理代码
    
# 例子
try:
    1 / 0
except:
    print("出错啦~")
 
出错啦~
# 正常情况输出:
try:
    1 / 1
except:
    print("出错啦~")
    
1.0

# 指定具体异常,当捕获的异常为指定异常才会执行except中内容
try:
    1 / 0
except ZeroDivisionError:
    print("出错啦~")

出错啦~
# 例子:
try:
    1 + "AAA"
except ZeroDivisionError: # 捕获异常不为Zero... 
    print("出错啦~")

Traceback (most recent call last):
  File "<pyshell#22>", line 2, in <module>
    1 + "AAA"
TypeError: unsupported operand type(s) for +: 'int' and 'str'
# 提取异常的原因 as     
try:
    1 / 0
except ZeroDivisionError as e:
    print(e)
division by zero

# 指定多个可能出现的异常
-- (ZeroDivisionError, ValueError, TypeError)
try:
    1 / 0
    1 + "AAA"
except (ZeroDivisionError, ValueError, TypeError):
    pass

# 分开处理多个异常
try:
    1 / 0
    1 + "AAA"
except ZeroDivisionError:
    print("除数不能为0!")
except ValueError:
    print("值之不正确!")
except TypeError:
    print("类型不正确!")

除数不能为0! # 捕获第一个后 后边的不作处理。跳过
try-except-else

try 语句中没检查到错误的内容,就会执行else语句中的内容。

# 异常
try:
    1 / 0
except:
    print("出错啦~")
else:
    print("没出错!")

    
出错啦~
# 无异常
try:
    1 / 1
except:
    print("出错啦~")
else:
    print("没出错!")

1.0
没出错!
try-except-finally

无论异常有没有发生,都会执行的内容

try:
    1 / 0
except:
    print("出错啦~")
else:
    print("没出错!")
finally:
    print("无异常 有异常 都要执行哦")

出错啦~
无异常 有异常 都要执行哦
# 常用于收尾工作,比如文件关闭。
try:
    f = open("FishC.txt", "w")
    f.write("I love FishC.")
except:
    print("出错咯~")
finally:
    f.close()

    
13
try-finally
try:
    while True:
        pass
finally:
    print("晚安~")
   
晚安~
Traceback (most recent call last):
  File "<pyshell#62>", line 2, in <module>
    while True:
KeyboardInterrupt

总结:

image-20220527180654935

异常的嵌套
try:
    try:
        520 + "A"
    except:
        print("内部异常啦")
    1 / 0
except:
    print("外部异常啦")
finally:
    print("收尾工作~~")

内部异常啦
外部异常啦
收尾工作~~

# 放在内部异常区前有异常,则内部try跳过
try:
    1 / 0
    try:
        520 + "A"
    except:
        print("内部异常啦")
except:
    print("外部异常啦")
finally:
    print("收尾工作~~")

    
外部异常啦
收尾工作~~
raise语句

主动引发异常,自爆

不能指定一个不存在的异常类型

raise ValueError("值不正确")
Traceback (most recent call last):
  File "<pyshell#80>", line 1, in <module>
    raise ValueError("值不正确")
ValueError: 值不正确
    
raise ValueError("这样不行~") from ZeroDivisionError
ZeroDivisionError
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
  File "<pyshell#81>", line 1, in <module>
    raise ValueError("这样不行~") from ZeroDivisionError
ValueError: 这样不行~
assert语句

主动引发异常:只能引发一个叫AssertionError的异常。通常代码调试用于。

s = "FishC"
assert s == "FishC"
assert s != "FishC"
Traceback (most recent call last):
  File "<pyshell#89>", line 1, in <module>
    assert s != "FishC"
AssertionError

利用异常来实现goto

try:
    while True:
        while True:
            for i in range(10):
                if i > 3:
                    raise
                print(i) # 打印小于 <= 3的
            print("被跳过!")
        print("被跳过!")
    print("被跳过!")
except:
    print("到这来了!")
    
0
1
2
3
到这来了!

类和对象

面向对象也是一种代码封装的方法

对象 = 属性 + 方法

类和对象的属性就是通过字典进行存放的。

在对象诞生之前,需要先创建一个类(class),然后通过类创造实际的对象。一个类可以创建无数个对象。

类名:约定俗成的使用大写字母开头

所谓属性就是写在类里边的变量,方法就是写在类里面的函数。

# 定义一个类:
class Turtle:
    head = 1
    eyes = 2
    legs = 4
    shell = True

    def crawl(self):
        print("人们总抱怨我动作慢吞吞的,殊不知如不积跬步无以至千里的道理")

    def run(self):
        print("虽然我行动汗漫,但如果遇到危险,还是会夺命狂奔的!")

    def bite(self):
        print("人善被人欺,龟善被人骑,我可是会咬人的")

    def eat(self):
        print("谁知盘中餐粒粒皆辛苦,吃得好,不如吃的饱")

    def sleep(self):
        print("Zzzz...")
运行:
================ RESTART: D:/Python/xuexiPY/class_turtle.py ================
定义一个对象:
t1 就是Turtle类的对象,也叫实例对象。它就拥有了这个类所定义的属性和方法。
t1 = Turtle()
调用类定义的属性和方法:
t1.head
1
t1.legs
4
t1.crawl()
人们总抱怨我动作慢吞吞的,殊不知如不积跬步无以至千里的道理
t1.bite()
人善被人欺,龟善被人骑,我可是会咬人的
t1.sleep()
Zzzz...

# 一个类可以创建无数个对象
t2 = Turtle()
t2.head
1
t2.crawl()
人们总抱怨我动作慢吞吞的,殊不知如不积跬步无以至千里的道理
-- 当一个对象被创建出来,就可以去修改他的值了。
t2.legs = 3
t2.legs
3
t1.legs
4
t1.mouth = 1
t1.mouth
1
dir(t1)
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'bite', 'crawl', 'eat', 'eyes', 'head', 'legs', 'mouth', 'run', 'shell', 'sleep']
dir(t2)
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'bite', 'crawl', 'eat', 'eyes', 'head', 'legs', 'run', 'shell', 'sleep']

封装

封装是面向对象编程的三个基本特征之一,另外两个是继承和多态。

封装就是在创建对象之前,通过类将相关的属性和方法打包到一起,然后通过类来生成相应的对象。

对象

python到处皆对象,

x = 520
type(x)
<class 'int'>
y = "F"
type(y)
<class 'str'>

# class中的 self:
-- self 就是本身实例对象本身,类C的实例对象c本身!
class C:
    def hello():
        print("你好")
    
c = C()
c.hello()
Traceback (most recent call last):
  File "<pyshell#30>", line 1, in <module>
    c.hello()
TypeError: C.hello() takes 0 positional arguments but 1 was given
    
class C:
    def get_self(self):
        print(self)
     
c = C()
c.get_self()
<__main__.C object at 0x00000295D7A77D30>
c
<__main__.C object at 0x00000295D7A77D30>

继承

python的类也是支持继承的,他可以使用现有类的所有功能,并在无需重新编写代码的情况下,对这些功能进行扩展,通过继承创建的新类我们称之为子类,而被继承的类我们称之为父类/基类/超类。

-- 继承
定义一个父类A,被B子类继承。
class A:
    x = 520
    def hello(self):
        print("你好 我是A")
定义子类B,继承父类A
class B(A):
    pass

b = B()
b.x
520
b.hello()
你好 我是A
-- 如果子类中出现同父类相同的属性名和方法名,则会覆盖父类中的值。
class B(A):
    x = 880
    def hello(self):
        print("你好 我是B")
      
b = B()
b.x
880
b.hello()
你好 我是B

-- isinstance()函数 判断某个对象是否属于某个类
isinstance(b, B)
True
isinstance(b, A) # 继承的父类,也是True
True

-- issubclass() 检查一个类是否为某个类的子类
issubclass(A, B)
False
issubclass(B, A) # B类是A类的子类
True

-- 多重继承
python的类是支持多重继承的,一个子类可以同时继承多个父类。
在Python中一个类能继承自不止一个父类,这叫做Python的多重继承。
多重继承 先去左边类中寻找,找不到才会去右边的寻找
class A:
    x = 520
    def hello(self):
        print("你好 我是A")
       
class B:
    x = 880
    y = 250
    def hello(self):
        print("你好 我是B")
        
class C(A, B):
    pass
class C.x
SyntaxError: expected ':'
c = C()

c.x
520
c.hello()
你好 我是A
多重继承 先去左边类中寻找,找不到才会去右边的寻找
c.y
250

# 组合
class Turtle:
    def say(self):
        print("不积跬步,无以至千里")
        
class Cat:
    def say(self):
        print("喵喵喵")
        
class Dog:
    def say(self):
        print("汪汪汪")
        
class Garden:
    t = Turtle()
    c = Cat()
    d = Dog()
    def say(self):
        self.t.say()
        self.c.say()
        self.d.say()
        
g = Garden()
g.say()
不积跬步,无以至千里
喵喵喵
汪汪汪

# 方法是公用的,属性是自己的,
class C:
    def get_self(self):
        print(self)
        
c = C()
c.get_self()
<__main__.C object at 0x0000021267E67E50>
c
<__main__.C object at 0x0000021267E67E50>
C.get_self(c)
<__main__.C object at 0x0000021267E67E50>
d = C()
d.x = 250
d.x
250
c.x
Traceback (most recent call last):
  File "<pyshell#79>", line 1, in <module>
    c.x
AttributeError: 'C' object has no attribute 'x'
c.x = 520
c.x
520
c.__dict__
{'x': 520}
d.__dict__
{'x': 250}
d.y = 660
d.__dict__
{'x': 250, 'y': 660}

-- 例子:
class C:
    def set_x(self, v):
        self.x = v
        
c = C()
c.__dict__
{}
c.set_x(250)
c.__dict__
{'x': 250}
c.x # c.x = self.x
250

-- 例子:
class C:
    x = 100 # 属性
    def set_x(self, v): #方法 x为局部变量
        x = v # 未绑定self,只是x变量
     
c = C()
c.set_x(250) #不会改变 x = 100 因为x为属性
c.x
100
C.x
100
# 修改类C的x属性。实例对象c会发生改变,因为此时c没有属于自身的属性,是通过类C实例过来的,所以去访问类C的属性
C.x = 250 # 不建议这么修改 因为会有其他对象用这个类
c.x
250
c.__dict__
{}

# 定义:
类和对象的属性就是通过字典进行存放的。
class C:
    pass

C.x = 250
C.y = "小甲鱼"
C.z = [1, 2, 3]
print(C.z)
[1, 2, 3]
print(C.y)
小甲鱼
print(C.x)
250
c = C()
c.x
250
c.__dict__
{}
c.x = 250
c.__dict__
{'x': 250}
c.y = "小甲鱼"
c.y
'小甲鱼'
c.__dict__
{'x': 250, 'y': '小甲鱼'}
c.z = [1, 2, 3]
c.__dict__
{'x': 250, 'y': '小甲鱼', 'z': [1, 2, 3]}
posted @ 2022-05-24 11:36  nice的  阅读(27)  评论(0编辑  收藏  举报