day 9 推导式和函数
1.列表推导式
1)基本结构
列表 = [表达式 for 变量 in 序列]
产生一个新的列表,列表中的元素就是每次循环对应的表达式的结果
相当于:
列表 = []
for 变量 in 序列:
列表.append(表达式)
list1 = [10 for x in range(3)]
print(list1) # [10, 10, 10]
list2 = [2*x for x in range(1, 4)]
print(list2) # [2, 4, 6]
2)条件结构
列表 = [表达式 for 变量 in 序列 if 条件语句]
相当于:
列表 = []
for 变量 in 序列:
if 条件语句:
列表.append(表达式)
list4 = [x for x in range(10) if x % 2]
print(list4) # [1, 3, 5, 7, 9]
list5 = [x for x in range(10) if x % 2 == 0]
print(list5) # [0, 2, 4, 6, 8]
# 练习1:写一个列表推导式,产生一个列表中的元素满足以下规律:str1,str3,str6,str9,...,str99
list6 = [f'str{x}' for x in range(1, 100) if x == 1 or x % 3 == 0]
print(list6)
list7 = ['str1' if x == 0 else f'str{x}' for x in range(0, 100, 3)]
print(list7)
多重循环结构:
列表 = [表达式 for 变量1 in 序列1 for 变量2 in 序列2]
列表 = []
相当于:
for 变量1 in 序列1:
for 变量2 in 序列2:
if 条件语句:
列表.append(表达式)
list8 = [f'{x}{y}' for x in range(3) for y in 'abc']
print(list8) # ['0a', '0b', '0c', '1a', '1b', '1c', '2a', '2b', '2c']
2.集合推导式
将列表推导式的[]变成{}
a1 = {x for x in 'hello'}
print(a1) # {'o', 'e', 'l', 'h'}
3.元组和字典推导式
元组 - 将列表推导式的[]变成tuple()
字典 - (表达式是键值对形式)将列表推导式的[]变成{};(表达式是有且只有两个元素的序列的时候)将列表推导式的[]变成dict()
a2 = tuple(x*2 for x in 'hello')
print(a2)
a3 = {x: x*2 for x in 'hello'}
print(a3)
a4 = dict((x, x*2) for x in 'hello')
print(a4)
# 练习3 通过字典推导式交换一个字典的键和值
dic = {'a': 10, 'b': 20, 'c': 30}
dic1 = {dic[key]: key for key in dic}
print(dic1) # {10: 'a', 20: 'b', 30: 'c'}
# 练习4 通过字典推导式交换一个字典的键和值,如果值是可变的新的字典中不交换
dic = {'a': 10, 'b': 20, 'c': [30, 20]}
dic1 = {dic[key]: key for key in dic if type(dic[key]) != list and type(dic[key]) != dict and type(dic[key]) != set}
print(dic1) # {10: 'a', 20: 'b'}
dic = {'a': 10, 'b': 20, 'c': [30, 20]}
dic1 = dict((key, dic[key]) if type(dic[key]) in (list, set, dict) else (dic[key], key) for key in dic)
print(dic1) # {10: 'a', 20: 'b', 'c': [30, 20]}
4.认识函数
1.没有函数会遇到什么问题
a.相同功能对应的代码需要重复写
b.一旦功能发生改变,需要将使用到这个功能的代码的位置全部修改
怎么解决:使用函数
a.什么是函数
函数就是对实现某一特定功能的代码的封装。(机器)
b.函数的分类(谁定义的函数)
系统函数:python已经定义好的,程序员可以直接使用的函数。例如:print、input、chr、ord、id、max、min、sum、sorted等(别人已经造好的机器)
自定义函数:由程序员自己定义,程序员可以自己使用或者给别人使用的函数。(自己造机器)
语法:
def 函数名(形参列表):
函数说明文档
函数体
说明:
1)def - 关键字;固定写法
2)函数名 - 程序员自己命名
要求:标识符、不能是关键字
规范:字母小写、单词之间用_隔开;
见名知义(看到函数名大概知道函数的功能)
不适用系统内的函数名、类型名和模块名
3)(): - 固定写法(不能省略)
4)形参列表 - 以’变量名1,变量名2,变量名3,…'的形式存在;
形参的作用是将函数外部的数据传递到寒素里面(如果实现函数的功能需要提供外部数据,那么这个函数就需要形参)
5)函数说明文档 - 函数的说明书;本质就是文档注释""""""引起来
6)函数体 - 和def保持一个缩进的一条或者多条语句(至少一条);
实现函数功能的代码段
(重点)注意:定义函数的时候不会执行函数体
# 示例1:定义一个函数求任意两个数字的和
def sum1(num1, num2):
"""
求两个数字的和 - (函数功能说明区)
:param num1: 提供第一个数字 - (参数说明)
:param num2: 提供第二个数字 - (参数说明)
:return: None - (返回值说明)
"""
print(num1 + num2)
# 练习2:写一个函数将两个字符串交叉合并
def merge(str1, str2):
str3 = ''
for index in range(min(len(str1), len(str2))):
str3 += str1[index] + str2[index]
# 再确定尾部
if len(str1) > len(str2):
str3 += str1[len(str2):]
else:
str3 += str2[len(str1):]
print(str3)
c.调用函数
语法:
函数名(实参列表)
说明:
函数名 - 需要使用的已经定义好的函数的函数名
() - 固定写法
实参列表 - 以’数据1, 数据2, 数据3,…'的形式存在;
实参就是需要从函数外部传递到函数内部使用的具体的数据(默认情况下被调用的函数有多少形参就需要提供多少个实参)
5.位置参数和关键字参数
5.1根据实参的传递方式将实参分为位置参数和关键字参数两种
1)位置参数
以’数据1, 数据2, 数据3, …'形式存在,让实参和形参一一对应
2)关键字参数
以’形参1=实参1, 形参2=实参2, …'形式存在,这个参数的位置可以随意更改
3)位置参数和关键字参数混用
位置参数必须在关键字参数的前面
5.2参数默认值
定义函数的时候可以直接给一个或者多个形参赋默认值;有默认值的参数在调用的时候可以不传参。
def func2(a=1, b=2, c=3):
print(f'a:{a}, b:{b}, c:{c}')
func2() # a:1, b:2, c:3
func2(10, 20) # a:10, b:20, c:3
func2(b=100) # a:1, b:100, c:3
# 有默认值的参数必须在没有默认值参数的后面
5.3不定长参数
定义函数的时候如果参数个数不确定,可以使用不定长参数
1)带的不定长参数在形参前加,让这个形参变成不定长参数,可以同时接受多个实参。这个参数的本质就是一个元组,传递对应的实参全部会变成这个元组中的元素。(必须使用位置参数传参)
2)带的不定长参数在形参前加让这个形参变成不定长参数,可以同时接受多个实参。这个参数的本质就是一个字典(必须使用关键字参数传参,关键字自己随意命名)
# 这儿的x必须使用位置参数传参
def func6(x, *a):
print('a:', a, 'x:', x)
# 这儿的x必须使用关键字参数传参
def func7(*a, x):
print('a:', a, 'x:', x)
def func8(**num):
print(num)
func8() # {}
func8(a=100) # {'a': 100}
func8(name='张三', age='30') # {'name': '张三', 'age': '30'}
面试题:func(args, **kwargs), 函数func中args, **kwargs有什么意义?
让函数调用的时候更加灵活
def func(*args, **kwargs):
pass