重要数据类型
列表数据类型
-
在实际开发中,经常需要将一组(不只一个)数据存储起来,以便后边的代码使用。列表就是这样的一个数据结构。且列表是Python中最基本也是最常用的数据结构之一。
-
什么是数据结构呢?
- 通俗来讲,可以将数据结构当做是某种容器,该容器是用来装载或者存储数据的。不同的数据结构决定了对数据不同的组织方式。
- 那么当数据被装载或者存储到了某个数据结构中后,那么就可以基于该数据结构的特性对数据进行不同形式的处理和运算。
-
列表的创建方式
-
创建一个列表,只要把逗号分隔的不同的数据元素使用方括号括起来即可。列表内的元素,可以是其它任意类型的数据,可多层嵌套列表,元素个数无限制。
-
alist = [1,2,3,4,5] items = [1,'john',12.34] #列表中可以存储任意类型的数据
-
-
列表元素:
- 存储在列表数据结构中的每一个数据被称为列表元素,简称元素。
-
列表索引:
- 列表中的每个元素都被分配一个数字作为索引,用来表示该元素在列表内所排在的位置。第一个元素的索引是0,第二个索引是1,依此类推。
-
访问列表内的元素
-
列表从0开始为它的每一个元素顺序创建下标索引,直到总长度减一。要访问它的某个元素,以方括号加下标值的方式即可。注意要确保索引不越界,一旦访问的 索引超过范围,会抛出异常。所以,一定要记得最后一个元素的索引是len(list)-1。
-
alist = [1,12.3,'john'] print(alist[2]) #'john' print(alist[0:2]) #[1, 12] print(alist[6]) #使用索引和切片的时候,不可以访问超出索引范围的元素
-
-
修改元素的值
-
直接对元素进行重新赋值
-
alist = [1,12.3,'john'] alist[1] = 100.123 print(alist)
-
-
删除元素
-
使用del语句或者remove(),pop()方法删除指定的元素。
-
alist = [1,12.3,'john'] # del alist[0] #删除下标为0的列表元素 # alist.remove('john') #删除列表中bobo这个列表元素 # alist.pop() #默认情况下pop会把列表中最后一个元素删除 alist.pop(2) #将列表中下标为2的元素进行删除 print(alist)
-
-
切片
-
切片指的是对序列进行截取,选取序列中的某一段。
-
切片的语法是: list[start:end]
-
#同字符串的切片机制一样 alist = [1,12.3,'john','jay','hello'] print(alist[:-1])
-
-
以冒号分割索引,start代表起点索引,end代表结束点索引。省略start表示以0开始,省略end表示到列表的结尾。注意,区间是左闭右开的!也就是说[1:4]会截取列表的索引为1/2/3的3个元素,不会截取索引为4的元素。分片不会修改原有的列表,可以将结果保存到新的变量,因此切片也是一种安全操作,常被用来复制一个列表,例如newlist = lis[:]。
-
切片过程中还可以设置步长,以第二个冒号分割,例如list[3:9:2],表示每隔多少距离取一个元素。
-
-
列表的内置方法
- 上文中我们说过,数据存储到不同的数据结构中,可以基于该数据结构的特性对数据进行指定形式的操作和处理。下图中的方法是列表专有的内置方法,请熟记于心。
-
alist = ['john',"18","99.5",'北京'] #将列表转换成字符串 ret = '-'.join(alist) #将列表中的每一个列表元素根据-为间隔进行拼接,返回字符串结果 print(ret) #如何将字符串转换成列表 s = 'hello-name-john-age' ret = s.split('-') print(ret) alist = [3,8,5,7,6,2,1] alist.sort() #对列表元素进行排序 print(alist) a = [1,2,3] a.append('john') #向列表尾部添加一个元素 print(a) a1 = [1,2,3] a1.insert(1,999) #向列表下标为1的位置添加一个元素 print(a1)
字典数据类型
-
字典的实现机制:
- Python的字典数据类型是基于hash散列算法实现的,采用键值对(key:value)的形式,根据key的值计算value的地址,具有非常快的查取和插入速度。
-
字典特性:
- 字典包含的元素个数不限,值的类型可以是任何数据类型!但是字典的key必须是不可变的对象,例如整数、字符串、bytes和元组,最常见的还是将字符串作为key。列表、字典、集合等就不可以作为key。同时,同一个字典内的key必须是唯一的,但值则不必。
- 注意:从Python3.6开始,字典是有序的!它将保持元素插入时的先后顺序!请务必清楚!
-
创建字典
-
字典的每个键值对用冒号(:)分割,每个对之间用逗号(,)分割,整个字典包括在花括号({})中 ,例如:
- d = {key1 : value1, key2 : value2 }
-
#键值对:key : value #key:只能使用不可变类型的数据充当,通常使用字符串 #value:任意数据类型的值充当 #字典中无法存储重复的键值对 dict_1 = {'name':'john','age':18,'score':100,'age':18} #注意:不要在字段中存储相同的key,value可以相同 dict_2 = {'name':'john','age':18,'age':20} print(dict_2)
-
-
访问字典
-
虽然现在的字典在访问时有序了,但字典依然是集合类型,不是序列类型,因此没有索引下标的概念,更没有切片的说法。但与list类似的地方是,字典采用把相应的键放入方括号内获取对应值的方式取值。
-
d = {'name':'john','age':20,"scores":[100,120,99]} #根据key访问对应的value值 print(d['name'],d['scores']) #依次访问name和scores对应的value值 print(d.get('name')) #通过get使用对应的key访问对应的value值 #注意:使用[]访问不存在的key对应的value值程序会报错 # print(d['adress']) #程序报错 #注意:使用get访问不存在的key程序不会报错,但是会返回None这个空值 print(d.get('address'))
-
get访问:
dic = {'name':'john','age':20,"scores":[100,120,99]} #2种字典元素访问的方式 print(dic['name']) # print(dic['address']) #key不存在则报错 print(dic.get('address')) #key不存在则返回None
-
-
添加和修改
- 增加就是往字典插入新的键值对,修改就是给原有的键赋予新的值。由于一个key只能对应一个值,所以,多次对一个key赋值,后面的值会把前面的值冲掉。
d = {'name':'john','age':20,"scores":[100,120,99]} d['name'] = 'jay' #给存在的key修改对应的value值 d['address'] = 'Beijing' #给一个不存在的key赋值表示新增键值对 del d['age'] #删除age键值对 print(d)
-
删除字典元素、清空字典和删除字典
- 使用del关键字删除字典元素或者字典本身,使用字典的clear()方法清空字典。
d = {'name':'john','age':20,"scores":[100,120,99],'name':'john'}
del d['name']
print(d)
d = {'name':'john','age':20,"scores":[100,120,99],'name':'john'}
del d
print(d)
d = {'name':'john','age':20,"scores":[100,120,99],'name':'john'}
d.clear()
print(d)
- 字典的重要方法
d = {'name':'john','age':20,"scores":[100,120,99]}
print('name' in d) #查看name是否存在于d字典的keys中
print(d.keys()) #返回字典中所有的key
print(d.values()) #返回字典中所有的value
print(d.items()) #返回字典中所有的键值对
练习(重点)
- 写一个程序,输出100以内的所有偶数,直到累加和大于1000停止程序。
#写一个程序,输出100以内的所有偶数,直到累加和大于1000停止程序。
sum = 0 #用来存储累加后的结果
for i in range(101): #range(101)返回就是0-100之间的一个序列
if i % 2 == 0:
if sum >= 1000:
break
sum = sum + i
print(sum)
- 已知a+b+c=1000且a2+b2=c^2(a,b,c都是自然数),求出符合条件的a,b,c的所有组合。
#已知a+b+c=1000且a^2+b^2=c^2(a,b,c都是自然数),求出符合条件的a,b,c的所有组合
for a in range(0,1001):#确定a的取值范围
for b in range(0,1001):#确定b的取值范围
c = 1000 - a - b
if a + b + c == 1000 and a**2 + b**2 == c**2:
print(a,b,c)
- 给定一个字符串string = “Hello, World!”,请统计字符串中每个字符的出现次数,并将结果存储在一个字典中。
#给定一个字符串string = "Hello",请统计字符串中每个字符的出现次数,并将结果存储在一个字典中。
string = "Hello"
char_count = {} #字典,用于保存每一个字符串的次数
for char in string:
if char not in char_count:
char_count[char] = 1
else:
char_count[char] += 1
print(char_count)
#{"H":1,'e':1,'l':2,'o':1}
- 猜数字游戏设计:可以不间断的进行猜数字游戏环节,找到猜对了,结束程序,猜不对,可以不断的进行游戏,并且需要提示用户猜打了还是猜小了。
- 最后需要统计出,用户猜了多少次才猜对。
- 每一个用户的初始分数为100,每猜错一次扣5分,最后程序结束,统计用户的得分
#电脑随机生成一个随机数
import random #工具箱
guess_num = random.randint(0,10) #使用random工具箱中的randint工具生成一个0-10之间的随机数
count = 0 #用于保存用户猜的次数(就是循环的次数)
score = 100 #初始分值
while 1:#死循环
count += 1
#让用户从键盘上录入一个数字
num = int(input('enter a num:'))
#判断num和guess_num是否一样
if num == guess_num:
print('猜对了')
break #只有猜对了,循环才会结束
elif num < guess_num:
print('猜小了')
score -= 5
else:
print('猜大了')
score -= 5
print('一共猜的次数:',count)
print('总计得分:',score)
函数
什么是函数?
所谓的函数其实就是Python语言中的一种工具,基于该工具可以完成不同的具体操作。想要将函数理解透彻,大家一定要善于映射生活,也就是基于我们熟悉的生活场景来理解函数。因为,所有的编程语言都是人设计的,只要是人设计的,那么设计灵感必定来源于现实生活。
函数可以分为两种,一种是内置函数,另一种是自定义函数
- 内置函数:
- 内置函数其实就是Python语言的开发者已经给我们设计好的工具,我们可以直接使用这些已经被设计好的工具或者函数完成相关的操作
- 自定义函数:
- 当然,Python语言的开发者们也无法将我们在不同需求中要使用的操作都设计成不同的函数或者工具,那么我们也可以向开发者那样自行设计定制我们专属功能的工具函数。
- 案例:当你在野外露营的时候,如果想生火,如果你身上恰好带了打火机(内置函数),则可以直接使用该工具自行完成生火操作,否则,你也可以自己利用现有环境下的资源自行制作取火工具(自定义函数)。
函数基础
- 自定义函数的使用要经过两个过程
- 函数的定义(制定)
- 函数的调用(使用)
返回值
当一个函数被调用结束后,该函数势必已经将一组操作执行结束了,如果在操作执行结束后,想要将一个结果返回给调用者,则就可以使用return语句实现。例如:使用温度计测量体温后,一定要将测量结果返回给温度计的使用者。
- 返回一个具体的值
def func():
name = 'john'
return name
ret = func()
print(ret)
- 返回一个表达式
def myAdd():
num1 = input('enter a num1:')
num2 = input('enter a num 2:')
num1 = int(num1)
num2 = int(num2)
return num1 + num2
ret = myAdd() #ret == num1 + num2
print(ret)
- 返回多个结果
def func():
a = 1
b = ['john','100']
c = 'jay'
return a,b,c
ret = func()
print(ret)
- 不写return默认返回None
def cal():
print('我是函数')
ret = cal()
print(ret)
- return后面的代码无意义
def func():
print('函数开始执行')
print('函数正在执行')
return 'over' #return作为函数结束的标识
print('函数执行结束')
func()
- 返回一个函数(适当理解)
def outer():
print('正在执行outer函数')
def inner():
print('正在执行inner函数')
print('outer函数执行结束')
return inner
ret = outer() #outer() == inner == ret
ret() #inner()
- 返回一个函数调用(适当理解)
def outer():
print('正在执行outer函数')
def inner():
print('正在执行inner函数')
return 123
print('outer函数执行结束')
return inner() #123 == inner()
ret = outer() #inner() == 123 == ret
print(ret)
函数参数
绝大多数函数在定义的时候需要接收一定数量的参数,然后根据实际调用时提供的参数的不同,输出不同的结果。函数的参数可以极大程度上增加函数的”通用性“。
#设计一个加法运算的函数
def addNums():
num1 = 10
num2 = 20
return num1 + num2
ret = addNums()
print(ret)
#增加函数的通用性
def addNums(num1,num2):
return num1 + num2
ret = addNums(910,280)
print(ret)
- 参数的两种称谓
- 形参
- 函数定义时,制定的参数叫做形参
- 实参
- 函数调用时,传递的参数叫做实参
- 形参
- 参数的不同种类
- 定义函数时,参数的名字和参数位置确定下来,函数的接口就固定了。Python函数的参数定义灵活度非常大,常用的单数类型有:
- 位置参数
- 默认参数
- 动态参数(适当理解)
- 定义函数时,参数的名字和参数位置确定下来,函数的接口就固定了。Python函数的参数定义灵活度非常大,常用的单数类型有:
位置参数
也叫必传参数或者顺序参数,是最重要的、也是必须在调用函数时明确提供的参数!位置参数必须按先后顺序,一一对应,个数不多不少的传递!
def add(a,b,c):
return a+b+c
ret = add(1,2,3)
x = y = z = 10
ret = add(x,y,z)
print(ret)
通常我们在调用函数时,位置参数都是按顺序先后传入。但是,如果在位置参数传递时,给实参指定位置参数的参数名,那么位置参数也可以不按顺序调用。
def student(name,sex,age):
return name,sex,age
student('john','male',20)
student(sex='male',name='john',age=20)
默认参数
在函数定义时,如果给某个参数提供一个默认值,这个参数就变成了默认参数,不再是位置参数了。在调用函数的时候,我们可以给默认参数传递一个自定义的值,也可以使用默认值。
def insertStuMsg(name,age=18):
print(name,age)
insertStuMsg('john',20)
注意:默认参数必须在位置参数后面,如果违反了这点,在语法层面直接是通不过的。
def insertStuMsg(age=18,name):
print(name,age)
动态参数
-
顾名思义,动态参数就是传入的参数的个数是动态的,可以是1个、2个到任意个,还可以是0个。在不需要的时候,你完全可以忽略动态函数,不用给它传递任何值。
-
Python的动态参数有两种,分别是:
- *args
- **kwargs
- 这里面的关键是一个和两个星号的区别,而不是args和kwargs在名字上的区别。
-
注意:
- 动态参数,必须放在所有的位置参数和默认参数后面!
-
*agrs
-
一个星号表示接收任意个参数。调用时,会将实际参数打包成一个元组传入形式参数。如果参数是个列表,会将整个列表当做一个参数传入。例如:
def func(*args):#动态参数 print(args) func(1,2,'three',[6,7])
-
如果想将每一个列表元素作为单独的参数进行传递,则需要使用一个星花符号即可
def func(*args): print(args) func(*[1,2,3,4,5])
-
-
**kwargs
-
两个星表示接受键值对的动态参数,数量任意。调用的时候会将实际参数打包成字典。例如:
def func(**kwargs): print(kwargs) func(k1=1,k2=2,k3='john')
-
如果我们传递一个字典并希望字典内的键值对一一最为参数被逐一传入,则只需要只用2个星花即可。
def func(**kwargs): print(kwargs) dic = { 'k1':1, 'age':20, 'k3':3 } func(**dic)
-
变量作用域(函数进阶)
-
讲到了函数就必须介绍变量的作用域相关。
- 作用域指的是变量的有效范围。变量并不是在哪个位置都可以访问的,访问权限取决于这个变量是在哪里赋值的,也就是在哪个作用域内赋的值。变量在哪个作用域内赋值,则表示该变量的作用域就是该区域,变量只可以在其作用域指定区域被访问。
-
形象理解:我们可以把程序当做是一座房子,房子里的各种家具和生活用品就是变量。那么,我们就会发现,马桶这个变量只可以在厕所这个局部的区域被使用。但是,笔记本电脑则可以在家里任何地方被使用。那么,映射在程序中,马桶就可以称之为“局部变量”,笔记本电脑就可以被称之为“全局变量”。
-
局部变量
- 定义在函数内部的变量拥有一个局部作用域,被叫做局部变量。(类、模块等同理)
-
全局变量
- 定义在函数外的拥有全局作用域的变量,被称为全局变量。(类、模块等同理)
num = 133 #全局变量
def func():
email = 'www.123.qq.com' #局部变量
print(email) #函数内部可以访问局部变量
print(num)
#print(email) #局部变量无法再函数外部被使用
print(num)
func()
global关键字
total = 0 # total是一个全局变量
def plus( a, b ):
total = a + b # total在这里是局部变量.
print('函数内部total:',total)
plus(10, 20)
print("函数外部total: ", total)
很明显,函数plus内部通过total = arg1 + arg2语句,新建了一个局部变量total,它和外面的全局变量total是两码事。而如果我们,想要在函数内部修改外面的全局变量total呢?使用global关键字!
-
global:
- 指定当前变量使用外部的全局变量
total = 0 # total是一个全局变量 def plus( a, b ): global total # 使用global关键字申明此处的total引用外部的total total = a + b print('函数内部total:',total) plus(10, 20) print("函数外部total: ", total)
匿名函数(初步认知)
-
匿名函数,就是一个没有名字的函数,本质上匿名函数是一种表达式。
-
匿名函数的使用可以省去了我们挖空心思为函数命名的麻烦,也能少写不少代码,很多编程语言都提供这一特性。匿名函数用好了,会有画龙点睛的效果,没用好,就容易“画虎不成反类犬”,需要我们在平时的代码过程中,多学、多看、多琢磨。
-
匿名函数的使用
- Python语言使用lambda关键字来创建匿名函数。
- 所谓匿名,即不再使用def语句这样标准的形式定义一个函数。
- lambda只是一个表达式,而不是一个代码块,函数体比def简单很多。
- 仅仅能在lambda表达式中封装有限的逻辑。
- 定义语法:
- 其形式通常是这样的:lambda 参数 : 表达式
- 匿名函数只能有一个表达式,不用也不能写return语句,表达式的结果就是其返回值。
def func(x):
if x > 0:
return 1
else:
return 0
func(-100)
ex = lambda x:1 if x > 0 else 0
ex(-10)
- 通常情况下,匿名函数是充当函数的参数来使用的,例如:
def isPass(s):
if s >= 60:
return '及格'
else:
return '不及格'
scores = [60,58,50,88,90,45]
ret = map(isPass,scores) #可以让isPass函数依次处理scores列表中的每一个列表元素
print(list(ret))
scores = [60,58,50,88,90,45]
ret = map(lambda x:'及格' if x >=60 else '不及格',scores)
print(list(ret))