python程序的构成
python程序是由一个个模块构成, 而一个模块对应python源文件文件, 一般后缀为.py; 而一个模块又由若干语句构成,当读取一个.py文件时,就是从上到下依次执行这些语句;所以语句是构成python程序的基本单元。
python的代码风格
python语句之间的包含关系是用缩进表示的,如下:
a = 10
if a>5:
print("我是被if包含的语句1")
print("我是被if包含的语句2")
print("我没有被if语句包含,我和if是同级语句")
上面的代码中,第一个和第二个print语句属于if语句,包含关系;而第三条print语句和if语句属于同级
连接符/
一行程序长度是没有限制的,但是为了可读性更强,通常将一行比 较长的程序分为多行;这时,我们可以使用\行连接符,把它放在行 结束的地方。Python解释器仍然将它们解释为同一行。如下
a = "133333ffffffffffffffssssssssssssssssssfca"
a = "133333ffffffffffffffsss" \
"sssssssssssssssfca"
b = [1,2,3,4,5,6,7,8,9,\
1,2,34,5]
b = [1,2,3,4,5,6,7,8,9,1,2,34,5]
对象的简单认识
python中的对象由三部分组成
- 标识:这里的标识简单的理解就是对象的地址,可以通过id()来查看地址值
- 类型:在这块内存地址上,存储的是什么类型的数据,可以通过type()来查看数据类型
- 值:在这块内存地址上,存储的是什么值
在python中,一切皆对象;对象的本质就是一个内存块,拥有特定的值,支持特定类型的相关操作
a = 520
print(id(a)) # 2433453979280
print(type(a)) # <class 'int'>
print(a) # 520
b = "Hello World"
print(id(b)) # 2433454589360
print(type(b)) # <class 'str'>
print(b) # Hello World
从上图可以看出,变量其实存储的是内存地址,变量通过内存地址找到对应的对象;这个操作也叫做对象的引用,即通过地址去引用对象
有一个重点内容就是:变量是没有数据类型的,对象是有数据类型的,怎么理解呢?变量从字面意思就是可变的量,即我可以在这一秒指向一个数值类型的对象,下一秒就可以指向一个字符串的对象,变量在字符串和数值或者其他类型的对象之间来回转换,没有一个类型是包括这些数据类型的,所以变量是没有数据类型的;而对象有数据类型,上面说到对象的三大组成部分,其中就有类型;第二点,python对一些数据类型内置了一些方法,对应的类型有对应的方法,如果没有数据类型,那么就无法使用这些对应的方法
标识符
上面提到的变量a,b啥的,这些就是表示符;但是并不是什么组合都是标识符,python中标识符的命名规则如下:
- 区分大小写:A 与 a 是两个不同的标识符
- 标识符由字母,数字,下划线构成,但是不能以数字开头
- 不能使用关键字
- 以双下划线开头和结尾的名称通常有特殊含义,尽量避免这种写法
对于不同地方的标识符,有如下的命名规范,不是强制的,但是这样的命名方式能够让别人一眼就认出这是什么变量
变量赋值
变量的声明和赋值:用于将一个变量绑定到一个对象上,格式:变量名 = 表达式
就像上图一样,将a和对象值为3的对象绑定,之后访问a其实就是访问3这个对象,b同上。什么是表达式呢,上面的a=3,3就是一个最简单表达式,所谓的表达式,就是最后结果会是一个值的式子。运行过程中,解释器 先运行右边的表达式,生成一个代表表达式运算结果的对象;然 后,将这个对象地址赋值给左边的变量
变量的删除和垃圾回收机制
当一个变量在后面的的程序代码中不会使用到,那么就可以将这个变量删除掉,删除掉的变量就不可以使用,而变量名指向的对象,当没有标识符指向这个对象时,就会被垃圾回收器回收,清空内存空间
a = 3
del a
print(a)
如上代码,将a赋值为3,再将a删除掉,再去访问a,那么系统将会报如下错误:
Traceback (most recent call last):
File "E:\python\learn_py\mypro001\mypy01.py", line 36, in <module>
print(a)
NameError: name 'a' is not defined
常量
所谓常量,就是不能改变的量,Python中不支持常量,也就是说没有语法去限制常量;在Python中有逻辑常量,我们只能约定常量的命名规则,以及在程序的逻辑上不对常量的值作出修改。大家遵守这样的一个规则,它就变成了常量。
常量命名规则:所有字符大写,多个单词之间使用下划线连接
MAX_SPEED = 120
print(MAX_SPEED) #输出120
MAX_SPEED = 140 # 实际是可以改的。只能逻辑上不做修改。
print(MAX_SPEED) #输出140
链式赋值
x=y=20 等价于 x=20,y=20,这样将一个对象赋值给多个变量,使用一行语句搞定的就是链式赋值
# 链式赋值
x = y = 20
print(x,y) # 20 20
系列解包赋值
x,y=20,30 等价于 x=20,y=30; 系列数据赋值给对应相同个数的变量(个数必须保持一致)
# 系列解包赋值
x, y = 20,30
print(x,y) # 20 30
常用于变量值交换,在其他语言中,如果想要将两个数的值对换,需要定义第三个变量,防止赋值时数值丢失,而Python不需要,直接使用x,y = y,x 即可实现变量交换
# 使用系列解包赋值实现变量交换
x,y = 20,30
x,y = y,x
print(x,y) # 20 30
最基本的内置数据类型
int:整型
四种表示方式:二进制(0b),十进制(默认),八进制(0o)以及十六进制(0x)
# 十进制
print(12) # 12
# 二进制
print(0b101) # 5
# 八进制
print(0o12) # 10
# 十六进制
print(0x12) # 18
在Python对int类型的长度是没有限制,也就是说它是无穷大的
类型转换
float => int:将会舍去小数点后面的数
bool => int:True=1,Float=0
str => int
①当字符串含义非数值型的字符,转换失败
②当字符串为float类型,转换失败
③当字符串为存数值型,可以实现转换
print("----类型转换----")
# int():类型转换
# float -> int : 舍去小数部分
print(int(9.9)) # 9
# bool -> int : True = 1, False = 0
print(int(True)) # 1
print(int(False)) # 0
# str -> int
# 1. 全字符型(没有数字)
# print(int("abc")) # ValueError: invalid literal for int() with base 10: 'abc'
# 2. 字母+数字型
# print(int("123a")) # ValueError: invalid literal for int() with base 10: '123a'
# 3. float型
# print(int("9.9")) # ValueError: invalid literal for int() with base 10: '9.9'
# 4. int型
print(int("123")) # 123
float:浮点型
浮点数的表示方式:3.14,同样表示3.14可以使用科学记数法来表示如:314e-1, 0.314e1
print(3.14) # 3.14
# 科学计数法
print(314e-2) # 3.14
print(0.314e1) # 3.14
类型转换
与int类似
# 类型转换
print(float(10)) # 10.0
print(float(True)) # 1.0
print(float(False)) # 0.0
print(float("9.9")) # 9.9
print(float("10")) # 10.0
#print(float("12a")) # ValueError: could not convert string to float: '12a'
# int 与 float 运算 结果是float
print(1+5.0) # 6.0
print("----四舍五入----")
# round(四舍五入)
print(round(9.5)) # 10
print(round(9.4)) # 9
print(round(9)) # 9
# round并不会修改原来的值,而是产生新的值返回出去
a = 9.5
b = round(a)
print(a) # 9.5
print(b) # 10
bool:布尔型
该类型就两个值, True or False, 在底层, True其实就是1, Flase就是0
在Python语言中有一些特殊的布尔类型值为False,例如False、0、0.0、空值None、空序列对象(空列表、空元祖、空集合、空字典、空字符串)、空range对象、空迭代对象。其他情况,均为True。
a = True
b = 3
c = a+b #c的值是:4
print(c)
print('空字符串的布尔类型的值:',bool(""))
#False
print('空列表布尔类型的值:',bool([]))
#False
print('None布尔类型的值:',bool(None))
#False
print('0布尔类型的值:',bool(0))
#False
print('字符串True和False转成布尔都是
True: ' ,bool("False")) #True
str:字符串类型
字符串的本质就是字符序列,python中不支持单个字符,即单个字符也是字符串
字符串是不可变的,当对字符串进行修改时,会报错
a = "abc"
a[0] = "c"
print(a)
# TypeError: 'str' object does not support item assignment
字符串的创建:如下四种方式
# 字符串的表示方式
str1 = "字符串1"
str2 = '字符串2'
str3 = """字符串3"""
str4 = '''字符串4'''
print(str1,str2,str3,str4)
python中实现这么多的字符串创建方式,在使用不同的引号时,是可以实现嵌套的,而同一种引号不能实现嵌套
# 实现在字符串中使用引号
str5 = "123 'hhhc'"
print(str5) # 123 'hhhc'
str6 = '123 "hhhc"'
print(str6) # 123 "hhhc"
如果想要同一种引号实现嵌套,则需要使用转义字符:+特殊符号
常见转义字符:\n换行,\t制表符,\r回车
str7 = "123 \"hhhc\""
print(str7) # 123 "hhhc"
字符串常见函数
len()函数可以计算字符串长度,也可以用于计算其他类型的长度,方便进行字符串的遍历
print(len("abc")) # 3
print(len("12345")) # 5
replace():前面提到过字符串不能修改,但是如果我们需要修改字符串怎么办,虽然字符串不能修改,但是变量可以修改,把变量指向其他字符串来实现字符串修改;replace(x,y)就是将字符串中的x替换为y,但是它不是修改变量的指向,而是返回一个新的字符串,如果需要修改字符串就需要将这个变量手动的指向这个返回的字符串,也就是赋值
# 如果想要对a的值进行替换,则使用replace
"""
下面a.replace并不是直接在a指向的对象上修改,而是创建了一个新的对象
再使用a变量去指向这个新的对象,从实现上来说是完成了字符串的替换
但是底层是创建新对象,再将变量指向这个新对象(指向新对象是我们手动加的)
当没有变量指向原来的对象时,原来的对象就会被垃圾回收机制删除掉
"""
a = "abcdefcaczfegasssxga"
a = a.replace('a',"z")
print(a) # zbcdefczczfegzsssxgz
str():实现其他数据类型转换成字符串,当我们调用print()函数时,解释器自动调用了str()将非字符串的对象转成了字符串
a = str(5.20) #结果是:a = ‘5.20’
b = str(3.14e2) #结果是:b = ’314.0’
c = str(True) #结果是:c = ‘True’
运算符
算术运算符
# 数字的基本运算符
# 除了正常的+,-,*
# 浮点数除法:计算出来的值是float
print(8/4) # 2.0
print(8/3) # 2.6666666666666665
# 整除:取整数部分
print(8//4) # 2
print(8//3) # 2
# 取余:取余数
print(8 % 4) # 0
print(8 % 3) # 2
# 求幂:指数运算
print(2 ** 3) # 2*2*2 = 8
print(2 ** 4) # 2*2*2*2 = 16
# divmod(x,y): 计算商和余,返回元组
print(divmod(13, 3)) # (4,1)
特殊的加法运算:
- 当运算符左右两边为数值型时,功能就是相加
- 当运算符左右两边为字符串类型时,功能就是字符串拼接
- 当运算符左右两边类型不一致时,报错
- 列表、元组等合并 [10,20,30]+[5,10,100] 结果是 [10,20,30,5,10,100]
特殊的乘法运算:
- 当运算符左右两边为数值型时,功能就是相乘
- 当运算符左右两边为字符串类型时,功能就是字符串复制
- 列表、元组等复制 [10,20,30]*3 结果是 [10,20,30,10,20,30,10,20,30]
增强型赋值运算符
a = 10
a += 2 # a = a + 2 = 12
print(a) # 12
a -= 2 # a = a - 2 = 10
print(a) # 10
a *= 2 # a = a * 2 = 20
print(a) # 20
a /= 2 # a = a / 2= 10.0
print(a) # 10.0
a //= 2 # a = a // 2 = 5.0
print(a) # 5.0
a **= 2 # a = a ** 2 = 25.0
print(a) # 25.0
a %= 2 # a = a % 2 = 1.0
print(a) # 1.0
逻辑运算符
a,b,c=10,20,30
print((a<b) and (b<c)) #and并且 输出结果是True
print((a>b) or (b>c)) #or或者 输出结果是False
print(not(b<c)) #not非 输出结果是False
短路与 和 短路或
与:同时为True,结果是True,当第一个结果是False时, 第二个值就不用计算了, 因为不管第二个值是否为True, 结果都是False,这就是短路与
或:其中一个结果为True,结果为True,也就是说当第一个值为True时,第二个值就不需要计算了,因为结果不管如何,这个表达式结果都是True
# 短路与
# 第二个表达式会弹出错误,因为0不能作为除数,但是运行不会报错,
# 就是因为第一个值为Flase,第二个值不计算,也就不运行了,不运行就不报错了
print(False and 3/0) # False
# 短路或
# 与短路与一致
print(True or 3/0) # True
比较运算符
a = 4
print(a<=30)
#关系运算符可以连用
if(3<a<10):
print("a在3和10之间")
位运算符
&:有0为0
|:有1为1
^: 有1有0为1
~:1变0,0变1
<<:左移几位相当于乘几个2,<<x = 相当与乘以x个2; >>:右移几位相当于除几个2
同一运算符
判断两个引用是否指向同一个对象,它与==的区别是:
同一运算符:比较的是对象的地址,而不是对象值
==:比较的是对象的值,默认调用__eq__()方法
a=20
b=20
c=30
print("a和b是同一个对象",a is b) #执行结果:True
print("a和c是同一个对象",a is c) #执行结果False
print("a和c不是同一个对象",a is not c) #执行结果True
在命令行中Python仅仅对比较小的整数对象进行缓存(范围为[-5, 256])缓存起来,也就是说当标识符指向的对象属于这个范围内,那么指向同一个数值的标识符它们的地址是一致的,超过这个范围的数字,指向它们的标识符的地址就是不一样的
文件模式下,所有数字都会被缓存,范围是:[-无穷大,+无穷大]),也就是说不论你数值为多少,只要是指向同一个数值的标识符,它们的地址都是一样的
成员运算符
a = "python"
b = "py"
print(b in a) #True
c = [10,20,30]
print(10 not in c) #False
一切都是数字
计算机中时间的表示是从“1970年1月1日 00:00:00”开始,以毫秒(1/1000秒)进行计算。我们也把1970年这个时刻称为“unix时间点”。这样,我们就把时间全部用数字来表示了。
python中可以通过time.time() 获得当前时刻,返回的值是以秒为单位,带微秒(1/1000毫秒)精度的浮点值。例如:1635063628. 5632517
import time
print(time.time()) # 1744337898.154824
b = int(time.time())
totalMinutes = b // 60
totalHour = totalMinutes // 60
totalDay = totalHour // 24
totalYear = totalDay // 365
print(b)
print(totalMinutes)
print(totalHour)
print(totalDay)
print(totalYear)
序列
列表
列表是一种数据存储方式,用来存储一系列的数据。存储的数据是可变的,可以是不同类型的;并且列表的大小会根据数据的变化来改变
列表的创建
- []
a = [10,20,30,40]
b = [] # 空列表
print(a,b) # [10, 20, 30, 40] []
- list():将任何可迭代的数据转化成列表
a = list(range(10))
b = list()
c = list("hhc,1109")
print(a) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(b) # []
print(c) # ['h', 'h', 'c', ',', '1', '1', '0', '9']
range()创建整数列表
range()可以帮助我们非常方便的创建整数列表,这在开发中及其有用。语法格式为:range([start,] end [,step]),返回的是一个range对象,需要通过list()转换为列表
print(type(range(3,15,2))) # <class 'range'>
a = list(range(3,15,2))
b = list(range(15,9,-1))
c = list(range(3,-4,-1))
print(a) # [3, 5, 7, 9, 11, 13]
print(b) # [15, 14, 13, 12, 11, 10]
print(c) # [3, 2, 1, 0, -1, -2, -3]
推导式生成列表
# 推导式生成列表
a = [x*2 for x in range(5)]
print(a) # [0, 2, 4, 6, 8]
b = [x*2 for x in range(100) if x%9 ==0]
print(b) # [0, 18, 36, 54, 72, 90, 108, 126, 144, 162, 180, 198]
列表操作
增加
- append():在列表的尾部增加,并且是原地修改,速度最快,最为推荐的方式
a = [20,40]
a.append(80)
print(a) # [20, 40, 80]
- +运算符操作:并不是真正的尾部添加元素,而是创建新的列表对象;将原列表的元素和新列表的元素依次复制到新的列表对象中
a = [20,40]
print(id(a)) # 2092880855168
a = a + [50]
print(a)
print(id(a)) # 2092880809088
- extend():将目标列表的所有元素添加到本列表的尾部,属于原地操作
a = [20,30]
b = [80,50]
print(id(a)) # 2869537964160
a.extend(b)
print(id(a)) # 2869537964160
- insert():可以将指定的元素插入到列表对象的任意制定位置。这样会让插入位置后面所有的元素进行移动,会影响处理速度。
a = [20,40,60,80]
a.insert(2,50)
print(a) # [20, 40, 50, 60, 80]
删除
删除的本质就是:元素的拷贝
下图就是将888这个元素删除,并将300和400向前移动
- del:删除列表指定位置的元素
a = [100,200,888,300,400]
del a[2]
print(a) # [100, 200, 300, 400]
- pop([index]):删除指定元素,并返回;如何没有携带参数,则默认删除尾部元素并返回
a = [10,20,30,40,50]
b1 = a.pop()
print(a,b1) # [10, 20, 30, 40] 50
b2 = a.pop(1)
print(a,b2) # [10, 30, 40] 20
- remove():删除首次出现的指定元素,若不存在该元素抛出异常
a = [10,20,30,20,50]
a.remove(20)
print(a) # [10, 30, 20, 50]
列表元素访问和计数
- 下标访问元素,范围[0-list.length-1],超出范围报错
a = [10,20,30,40,50,20,30,20,30]
print(a[5]) # 20
# print(a[10]) # IndexError: list index out of range
- index(x,[start],(end)):获取x在列表第一次出现的位置,也可以指定范围,没有报错
a = [10,20,30,40,50,20,30,20,30]
print(a.index(20)) # 1
print(a.index(20,2)) # 5
print(a.index(20,2,6)) # 6
# print(a.index(20,2,5)) # ValueError: 20 is not in list 不包括6
# print(a.index(20,2,4)) # ValueError: 20 is not in list
- count(x):x在列表中的出现次数
a = [10,20,30,40,50,20,30,20,30]
print(a.count(20)) # 3
- len(list):获取列表长度
a = [10,20,30,40,50,20,30,20,30]
print(len(a)) # 9
- is , not is
a = [10,20,30,40,50,20,30,20,30]
print(20 in a) # True
print(60 in a) # False
print(60 not in a) # True
切片
与字符串一致
a = [10,20,30,40,50,20,30,20,30]
print(a[:]) # [10, 20, 30, 40, 50, 20, 30, 20, 30]
print(a[1:]) # [20, 30, 40, 50, 20, 30, 20, 30]
print(a[:2]) # [10, 20]
print(a[1:3]) # [20, 30]
print(a[::2]) # [10, 30, 50, 30, 30]
print(a[-3:]) # [30, 20, 30]
print(a[-5:-3]) # [50,20]
print(a[::-1]) # [30, 20, 30, 20, 50, 40, 30, 20, 10]
列表的遍历-for
# 遍历
a = [10,20,30,40]
for obj in a:
print(obj,end=" ") # 10 20 30 40
复制所有列表元素
a = [10,20,30,40]
print(id(a)) # 2416422210432
b = [] + a
print(id(b)) # 2416422209216
print(b) # [10, 20, 30, 40]
列表排序
- sort():默认为升序排序,reverse=True为降序,修改原来的列表
import random
a = [20, 10, 30, 40]
random.shuffle(a)
a.sort()
print(a) # [10, 20, 30, 40]
a.sort(reverse=True)
print(a) # [40, 30, 20, 10]
- sorted():和sort一致,只是这个不行修改原列表,而是创建新列表
import random
a = [20, 10, 30, 40]
random.shuffle(a)
print(a) # [10, 20, 40, 30]
b = sorted(a)
print(a) # [40, 20, 10, 30]
print(b) # [10, 20, 30, 40]
- reversed()返回迭代器
a = [20, 10, 30, 40]
b = reversed(a)
print(b) # <list_reverseiterator object at 0x0000028482B032B0>
print(list(b)) # [40, 30, 10, 40] 进过测试不能排序
print(list(b)) # [] 迭代器只能使用一次
内置函数
a = [3,10,20,15,9]
print(min(a)) # 3
print(max(a)) # 20
print(sum(a)) # 57 列表求和
多维列表
a = [
["高小一",18,30000,"北京"],
["高小二",19,20000,"上海"],
["高小五",20,10000,"深圳"],
]
print(a[1][0],a[1][1],a[1][2]) # 高小二 19 20000
元组
元组和列表不同,元组是不可变序列,也就是说元组里面的元素是不能修改的,所以元组也就没有对元素的增,删,改的相关方法
元组的创建
元组创建方式一:变量 = (元素),如果是单个元素,则需要再元素后面加一个逗号,如果不加逗号,则会认为是int类型的值
a = (10,20,30)
print(a,type(a)) # (10, 20, 30) <class 'tuple'>
b = 10,20,30
print(b,type(b)) # (10, 20, 30) <class 'tuple'>
c = (10)
print(c,type(c)) # 10 <class 'int'>
d = (10,)
print(d,type(d)) # (10,) <class 'tuple'>
e = 10,
print(e,type(e)) # (10,) <class 'tuple'>
元组创建方式二:通过tuple(可迭代对象)
a = tuple()
b = tuple("abc")
c = tuple(range(3))
d = tuple([2,3,4])
print(a) # ()
print(b) # ('a', 'b', 'c')
print(c) # (0, 1, 2)
print(d) # (2, 3, 4)
元组创建方式三:生成器推导式创建元组
列表推导式直接生成列表对象,生成器推导式生成的不是列表也不是元组,而是一个生成器对象。我们可以通过生成器对象,转化成列表或者元组。也可以使用生成器对象的 next() 方法进行遍
s = (x*2 for x in range(5))
print(s) # <generator object <genexpr> at 0x0000012F79C730D0>
# b = list(s) # [0, 2, 4, 6, 8]
# print(b)
c = tuple(s)
print(c) # (0, 2, 4, 6, 8)
s2 = (x for x in range(3))
print(s2.__next__()) # 0
print(s2.__next__()) # 1
print(s2.__next__()) # 2
# print(s2.__next__()) # StopIteration
历,或者直接作为迭代器对象来使用。
元组元素的访问和计数
- 元组的元素是不能修改的
# 元组不能修改
a = (20,10,30,9,8)
#a[3] = 33 # TypeError: 'tuple' object does not support item assignment
- 元组的访问
print(a[3]) # 9
print(a.index(30)) # 2
print(a.count(10)) # 1
print(a[1:3]) # (10, 30)
print(a[:4]) # (20, 10, 30, 9)
- 元组的排序 元组的元素是不能修改的,而关于排序的sort是原地修改的,所以元组没有该方法,但是可以使用内置函数sorted(),生成新的列表对象
a = (20,10,30,9,8)
a = sorted(a)
print(a) # [8, 9, 10, 20, 30]
- zip(列表1,列表2,...)将多个列表对应位置的元素组合成为元组,并返回这个zip对象。
a = [10,20,30]
b = [40,50,60]
c = [70,80,90,100]
d = zip(a,b,c)
print(d) # <zip object at 0x00000266A13DCE40>
e = tuple(d)
print(e) # ((10, 40, 70), (20, 50, 80), (30, 60, 90))
字典
字典是“键值对”的无序可变序列,字典中的每个元素都是一个“键值对”,包含:“键对象”和“值对象”。可以通过“键对象”实现快速获取、删除、更新对应的“值对象”。
键:不可变且不能重复的值:字面量,元组
值:任意数据,可以重复:所有数据
字典的创建
通过{}和dict()
a = {'name':'hhc','age':18,'job':'programmer'}
print(a) # {'name': 'hhc', 'age': 18, 'job': 'programmer'}
b = dict(name='hhc',age=18,job='programmer')
print(b) # {'name': 'hhc', 'age': 18, 'job': 'programmer'}
a = dict([("name","hhc"),("age",18)])
print(a) # {'name': 'hhc', 'age': 18}
c = {}
d = dict()
通过zip
k = ['name','age','job']
v = ['hhc',18,'teacher']
d = dict(zip(k,v))
print(d) # {'name': 'hhc', 'age': 18, 'job': 'teacher'}
通过fromkeys:这个方式是提供键,值默认为none
f = dict.fromkeys(['name','age','job'])
print(f) # {'name': None, 'age': None, 'job': None}
字典的访问
通过键获取值:
dict[键]:如果键不存在,则报错
dict.get(键,[默认值]):键不存咋则为None,也可以设置默认值,当键不存在时,返回默认值
print(a["name"]) # hhc
# print(a["sex"]) # KeyError: 'sex'
print(a.get("name")) # hhc
print(a.get("sex")) # None
print(a.get("sex","男"))# 男
获取所有的键值对
print(a.items()) # dict_items([('name', 'hhc'), ('age', 18), ('job', 'programmer')])
获取所有的键和值
print(a.keys()) # dict_keys(['name', 'age', 'job'])
print(a.values()) # dict_values(['hhc', 18, 'programmer'])
其他
# len
print(len(a)) # 3
# in
print("name" in a) # True
print("sex" in a) # False
字典元素的添加,修改和删除
添加:通过键,如果键不存在,则添加;如果键存在,则修改
a ={'name':'hhc','age':18,'job':'programmer'}
# 如果访问的键不存在,则新建,存在则修改
a["address"] = "cq"
a["age"] = 21
print(a) # {'name': 'hhc', 'age': 21, 'job': 'programmer', 'address': 'cq'}
a.update(b):字典a与字典b元素进行比较,如果键不存咋,则添加,如果存在,则将值修改为b的值
a = {'name':'hhc','age':18,'job':'programmer'}
b = {'name':'lcl','money':1000,'gender':'男的'}
a.update(b)
print(a) # {'name': 'lcl', 'age': 18, 'job': 'programmer', 'money': 1000, 'gender': '男的'}
删除:del(),clear(),pop()
a = {'name': 'lcl', 'age': 18, 'job': 'programmer', 'money': 1000, 'gender': '男的'}
del(a["money"])
print(a) # {'name': 'lcl', 'age': 18, 'job': 'programmer', 'gender': '男的'}
a.pop("job")
print(a) # {'name': 'lcl', 'age': 18, 'gender': '男的'}
a.clear()
print(a) # {}
popitem():随机删除和返回该键值对
a ={'name':'gaoqi','age':18,'job':'programmer'}
r1 = a.popitem()
r2 = a.popitem()
r3 = a.popitem()
print(a) # {}
序列解包
默认获取的是键
s = {'name':'gaoqi','age':18,'job':'teacher'}
a,b,c=s
print(a,b,c) # name age job
获取键值对
a, b, c = s.items()
print(a,b,c) # ('name', 'gaoqi') ('age', 18) ('job', 'teacher')
获取值
a, b, c = s.values()
print(a,b,c) # gaoqi 18 teacher
字典的核心底层
字典对象的核心是散列表。散列表是一个稀疏数组(总是有空白元素的数组),数组的每个单元叫做bucket。每个bucket有两部分:一个是键对象的引用,一个是值对象的引用。
字典的存:计算键的散列值,这里默认这个数组大小为8,取出散列值最后三位,计算其十进制,通过这个十进制去找数组中对应的下标,如果该下标没有数据,则将这个数据存入该位置。如果有数据就继续取三位重新上面的操作。(python会通过数据的拥挤程度自动扩容)
字典的取:计算键的散列值,取出散列值最后三位,计算其十进制,通过这个十进制去找数组中对应的下标,如果该下标没有数据,则返回None。如果有数据,则取出该数据的键,计算该键的散列值,与上面的散列值比较,如果一致就返回该数据,如果不存在继续上面的操作。