语法进阶
一、列表推导式
想讲解一下示例4到示例7的代码:
-
4、循环n次生成n个零放进列表中,其实也就是相当于[0]*n(列表乘法,将原来的列表循环n次产生一个新的列表),接着在循环n次产生n个这样的列表,最终就是[[0,0,0,…n个零],[0,0,0,0,0,…n个零],…n个这样的列表]也就是nXn的零矩阵
-
5、fib : fib[n] = fib[n-1]+fib[n-2]
第n个数等于第n-1个数加上第n-2个数,先生成一个列表,里面放初始值0和1,作为第一个和第二个斐波那契数,循环n-2次,每一次都是列表最后一个元素和他前一个元素进行相加所以索引是-1和-2,然后每次都把这个相加的添加到列表中,最后一个元素索引是n-1嘛,然后索引是走n-2步到达最后,所以循环是n-2次 -
6、for in语句就是从左往后读的,将matrix矩阵中的行拿出来,再将每个行中的每个元素拿出来打印这个元素
这里的事例7实际上是字典推导式:
字典推导式概述
字典推导式是 Python 中一种简洁的创建字典的方式,它允许你在一行代码中根据一定的规则生成字典。其基本语法如下:
{键表达式: 值表达式 for 变量 in 可迭代对象}键表达式 用于生成字典的键,值表达式 用于生成字典的值,变量 是在迭代过程中依次取到可迭代对象中的每个元素,可迭代对象 可以是列表、元组、字符串、range 对象等。
语法结构
字典推导式的基本语法如下:
{键表达式: 值表达式 for 变量 in 可迭代对象}
键表达式:用于生成字典的键,可以是简单的变量,也可以是经过某种计算或转换后的结果。
值表达式:用于生成字典的值,同样可以是简单的变量,或者是经过处理后得到的结果。
变量:在迭代过程中依次取到可迭代对象中的每个元素。
可迭代对象:可以是列表、元组、字符串、range 对象等任何支持迭代的对象。# 示例 1:将列表元素作为键,元素的平方作为值
nums = [1,2,3,4]
my_dict = {num:num**2 for num in nums}
print(my_dict)
# 使用字符串生成字典
word = "hello"
char_index_dict = {char:index for char,index in enumerate(word)}
print(char_index_dict)
# 带有条件判断的字典推导式
# 你还可以在字典推导式中添加条件判断,只选择满足特定条件的元素来生成字典。语法:
# {键表达式: 值表达式 for 变量 in 可迭代对象 if 条件表达式},其实就和列表推导式里的if是一样的,筛选出的值才能作为键
# 筛选出偶数的平方
nums = [1,2,3,4]
my_o_dict = {num:num**2 for num in nums if num%2 == 0}
print(my_o_dict)
# 多个可迭代对象的字典推导式
# 可以使用嵌套的 for 循环来处理多个可迭代对象。语法如下:
# {键表达式: 值表达式 for 变量1 in 可迭代对象1 for 变量2 in 可迭代对象2}
# 示例 4:结合两个列表生成字典
# 由于第二层循环每次都全部遍历完全,所以每一个值都是最后一个被覆盖的值
list1 = [1,2,3,4]
list2 = [2,3,4,5]
my_list = {l1:l2 for l1 in list1 for l2 in list2}
print(my_list)
# 如果想实现两个列表的值一个是键,一个是值,使用zip函数(将两个可迭代对象的对应元素打包生成一个元组,只有在用的时候才会生成元组,惰性求值),生成对应位置元组的迭代器,使用的时候才会生成元组,为了节省空间
list1 = [1,2,3,4]
list2 = [2,3,4,5]
my_list = {l1:l2 for l1,l2 in zip(list1,list2)}
print(my_list)
这里讲解一下zip函数吧:
# zip函数:在需要同时处理多个可迭代对象中对应位置的元素时非常方便。
# 它可以将多个可迭代对象(如列表、元组、字符串等)中对应位置的元素打包成一个个元组,然后返回一个由这些元组组成的迭代器。
# zip(*iterables)
# *iterables 表示接收任意数量的可迭代对象作为参数。这些可迭代对象可以是列表、元组、字符串等。
# 两个列表的打包
list1 = [1,2,3,4,5]
list2 = [4,5,6,7,8]
zip1=zip(list1,list2)
list3 = list(zip1)
print(list3)
# 多个可迭代对象的打包
list1 = [1,2,3,4,5]
tuple1 = (2,3,4,5)
str1 = "https"
zip1=zip(list1,tuple1,str1)
# 结合 for 循环使用
# zip 函数返回的迭代器通常会结合 for 循环来使用,方便对打包后的元素进行处理。
name1 = ["Alice","Mark","Tom"]
ages = [26,18,19]
for name,age in zip(name1,ages):print(f"{name}的年龄是{age}")
# 不同长度的可迭代对象
# 当传入的可迭代对象长度不一致时,zip 函数会以最短的可迭代对象的长度为准进行打包,超出部分会被忽略。
list1 = [1,2,3,4]
list2 = [2,3]
for l,s in zip(list1,list2):print(f"{l}对应{s}")
# zip 函数的逆操作
# 可以使用 * 操作符和 zip 函数来实现 zip 函数的逆操作,将打包后的元素解包回原来的可迭代对象。
list1 = [(1,2),("h",'m')]
for l in zip(*list1):print(l)
# zip 函数返回的是一个迭代器,这意味着它是惰性求值的,只有在迭代时才会实际生成元组。如果需要多次使用打包后的结果,建议将其转换为列表或其他可重复访问的数据结构。
# 当传入的可迭代对象为空时,zip 函数会返回一个空的迭代器。
#
列表推导式:
# 列表推导式
# 列表推导式的基本语法如下:
# [expression for item in iterable]
# expression:这是一个表达式,用于对 item 进行处理,最终生成列表中的元素。
# item:表示从可迭代对象 iterable 中取出的每个元素。
# iterable:是一个可迭代对象,例如列表、元组、字符串、集合等。
# 例子1:是列表中每一个数据平方
num = [1,2,3,4]
nums = [(element**2) for element in num ]
print(nums)
# # 将字符串中所有字符进行取出,放在一个列表中
str = "hello"
str_list = [element for element in str]
print(str_list)
# 带有条件语句的列表推导式:
# 列表推导式还可以包含条件语句,语法如下:
# [expression for item in iterable if condition]
# condition:是一个布尔表达式,用于筛选符合条件的元素。只有当 condition 为 True 时,expression 才会被添加到列表中。
# 例子:取出列表中的偶数并平方
num = [1,2,3,4,6]
num_list = [element**2 for element in num if element % 2==0 ]
print(num_list)
#
二、range函数
- 事例3:步长为负说明相邻两个数之间差倒序关系,可见相邻两个数之间差|步长|-1个数
- 事例4:从0到n*2中取出每一个数,将每一个数都取模n得到它的索引值,索引值每次到n都会清零,然后只需要n * m个数就可以达到m次循环索引
- 事例5:从左往右看for in语句,取出行的值,是0和1。每次取出一个行的值,都取出所有列的值,0和1和2,所以最终形成如上面所示网格矩阵
三、双端队列
栈:只能一端进,一端出(后进先出)----想象一叠盘子摞在一块,你每次都必须只拿最上面的盘子
队列:一端进入,另一端出,一般我们都是又进左出的---------相当于排队,也就是先排队的人结完账就走了,后面的人还得等着(先进先出)
双端队列:两端都可以进出,具有栈和队列的结合性,一端进出就是栈,一端进一端出就是队列
1、队列
queue是队列的意思,所以define+queue就是deque
- 注意导包,要导入队列包
- 给队列初始化一个对象以便后续使用
- 入队列采用append因为从右端进入
- 出队列从左端出,所以采用popleft(),而不是使用pop()他是默认移除并取出最右端一个元素,注意是有返回值的将元素从队列中移除并取出作为返回值
- 获取队列的长度选择使用len函数
2、栈
- 初始化一个列表,用来存放栈数据。
- 入栈:使用append方法在栈的尾部添加元素
- 出站使用pop每次移除并且取出最后一个元素
- 栈顶元素位于最后一个元素所以索引是-1
3、一些实用的小技巧
- 1、if not 条件 语句是当条件不满足时才执行if里面的语句,也就是q有值才可以执行后面的语句
- 2、不仅是将栈翻转,将序列翻转都可以使用[::-1]
- 3、队列可以转换成列表可迭代对象方便后续使用
- 4、直接初始化,之前介绍过迭代器,不将值存进内存中,只是记住值在内存中的位置,需要的时候便去访问它,节省了内存,也是惰性求值,在有需要的时候才去真正的计算它或者访问值
四、判断素数
1、基础判断素数逻辑:
- 素数是只能被1和它本身除的数
- 首先导入库,sys和math
- 先定义一个之前说过的输入函数,读取每一行数据并且将他们前后空格符规整去掉
- 定义是否为素数函数:小于2的数不会是素数所以直接返回faluse,将这个数从2到n-1每个数都取模,出现一个取模为0的就不是素数,说明这个数是它的因数
- 进阶版的:由于根号n*根号n = n,所以n这个数的因数有一个是大于等于根号n的,有一个是小于等于根号n的,所以只找到2到根号n的数去被取模就可以了,如果n取模这些数有等于0的,就不是素数。返回false,最终如果都没有提前返回false就返回true
- 输入n,打印函数的返回值(true or false)
2、埃氏筛判断素数原理:
原理:不通过计算(之前是通过计算的比较麻烦),我们可以在2到根号n之间的数找到一些素数,然后划掉这些素数的倍数,因为这些数的倍数都有这个素数作为因数,然后这些数的倍数就不是素数,具体划掉的过程是这样的:
- 从这个素数i的平方开始划掉,直到n,因为对于它的平方(i*i)之前的它的倍数都被其他的素数划掉了,2 * i ,3 * i,4 * i等等一直到(i-1) * i,都被这些2,3素数在遍历他们的倍数的时候划掉了,而像4 * i这种的也被当成2这个素数的倍数划掉过了
- 步长为i,因为他的倍数都是相隔i个数,2i,3i…
- 讲这些倍数划掉之后,剩下的就是素数,然后可以将这些数添加到素数列表中
import sys
from math import *
# 埃氏筛
n = int(input())
primes = [] # 定义一个素数列表存储素数
is_primes = [True] * (n+1) # 产生全真的真值列表代表是否是素数,一共有n个数
# 产生含有n+1个真值的列表,因为列表下表索引是从0开始的,多了一个真值给0这个数,
# 想索引对应的数的时候可以直接使用is_prime[3]代表3这个数的是否是素数的真值,
# 实质:索引(素数)直接对应相应位置存储是否是素数的真值(True or false)
# 开始划掉素数相对应的倍数
for i in range(2,int(sqrt(n))+1):# 从2到根号n这些数之间找素数(之前进阶版提到过)for j in range(i*i,n+1,i): # 从i方开始划掉数,步长是i,一直划到n,根号n的平方是nis_primes[j] = False # 将这些倍数置为false
for i in range(2,n+1): # 从2到n遍历,索引是true的就是素数if is_primes[i]:primes.append(i)
print(primes)
五、逆波兰表达式:
一般我们习惯使用中缀表达式,但是为了计算机方便读取我们可以使用前缀后缀表达式,逆波兰表达式就是后缀表达式,不需要括号来标明操作符的优先级
比如传进来a,b,+这种来运算 (比如是1,2,+)
- eval_rpn 是函数名,它接受一个类型为 list[str] (即字符串列表)的参数 tokens,-> int 表示这个函数最终返回的值是一个整数类型。
- stack栈列表
- ops是一个字典,每一个运算符都对应一个函数功能
- 把传入的字符串列表中的元素遍历,如果是操作符则把栈中的两个元素都pop出栈,然后再栈后添加上a和b使用函数功能运算后的结果
- 如果不是字符,那么就是数字字符串,把它转换为整形元素添加到栈中,列表中的元素前两个一定是数字字符串,所以可以保证到字符串的时候可以有两个数字出栈
- 最终栈列表中只剩下一个元素即计算后的结果
- 返回栈中剩的唯一一个元素,就是计算结果
传进来一个列表,比如是[‘1’,‘2’,‘+’],第一个和第二个都不在字符字典中所以走到else,都转换为int类型放入stack=[“1”,“2”],在到“+”走到if1语句里面,将a和b移除并取出,作为ops键“+”的函数的参数进行计算将返回值添加到stack中,这时候,stack中只剩下[3]了,最后返回索引为0的元素即结果
in语句的讲解:
# in 语句的讲解
# in 运算符用于判断一个元素是否存在于某个可迭代对象中,可迭代对象包括列表(list)、元组(tuple)、字符串(string)、集合(set)、字典(dict)等。
my_list = [1,2,3]
if 1 in my_list:print("right")
# 子字符串是否在字符串中
my_str = "hello"
if "ll" in my_str:print("right")
# 字典中的键是否在字典中:
my_dict = {"hello":1,"he":2,"hi":3}
if "he" not in my_dict:print("no")
else:print("yes")
# 与and或or一起使用:
my_list = [2,3,4,5]
my_str = "hello"
if 2 in my_list and "ll" in my_str:print("yes")
if "o" in my_str or 9 in my_list:print("or")
# 应用场景
# 数据验证:检查用户输入是否在允许的范围内。例如,验证用户输入的选项是否在可选列表中。
my_list = ["A","B","C"]
if input() in my_list:print("输入有效")
else:print("输入无效")