Python基础语法练习题(40-42)

接下来是今天的另外三题。

第四十题,计算列表元素之积:

复制代码
# 定义一个函数,该函数接收一个整数列表作为参数,并返回列表中所有元素的积

#方法一

# 定义函数
def multiply_list(lst):
    """
    计算列表中所有元素的积
    :param lst: 整数列表
    :return: 所有元素相乘的结果
    """
    result = 1          # 关键:初始值为 1(乘法单位元),不能是 0
    for i in lst:
        result *= i     # 逐个累乘
    return result

# 给定列表
Li = [1, 2, 3, 4, 5]

# 调用函数
print(multiply_list(Li))

#方法二

import math

def multiply_list(lst):
    return math.prod(lst)

#方法三

# from functools import reduce
#
# def multiply_list(lst):
#     return reduce(lambda x, y: x * y, lst)

以下是代码块逻辑分析:

计算列表元素之积

题目要求:给一个整数列表,把里面所有元素乘到一起,返回最终的积。比如列表 1、2、3、4、5,结果就是 1×2×3×4×5 = 120。

核心思路:和"求和"是同一套,只把加号换成乘号、初始值换成 1 这道题本质上就是上一类累加问题的翻版,代码里同样给了三种写法。方法一最朴素:定义 multiply_list,用一个变量 result 存结果,遍历列表把每个元素乘进去(result *= i 就是 result = result * i 的简写),最后返回。这里最关键的一点在注释里也点明了------result 的初始值必须是 1,不能是 0。因为 1 是乘法的单位元,任何数乘 1 还是它本身;要是写成 0,0 乘任何数都得 0,结果永远是 0,整个计算就废了。方法二直接调用标准库 math 里的 prod 函数,一行 math.prod(lst) 就搞定,是 Python 3.8 以后专门用来算连乘的现成工具。方法三用 functools 的 reduce 配合 lambda,把"两两相乘"这个动作在列表上反复滚动执行,属于函数式写法,思路更抽象。

举个例子 列表是 1、2、3、4、5。方法一从 result=1 开始,依次乘 1 得 1、乘 2 得 2、乘 3 得 6、乘 4 得 24、乘 5 得 120,返回 120。方法二 math.prod 内部做的是一模一样的连乘,同样返回 120。方法三 reduce 则是先算 1×2=2,再 2×3=6,再 6×4=24,最后 24×5=120。

几个细节 第一,初始值 1 是这道题的命门,和求和题初始值用 0 正好相反,一定要记清"加法从 0 起、乘法从 1 起"。第二,方法二和方法一函数同名 multiply_list,后定义的会覆盖前面的,同一文件里最终生效的是最后一个,这点要注意。第三,方法二、三都需要先导入对应的模块(math、functools),方法三整段被注释掉了,用时得取消注释。第四,如果列表里混进 0,结果必然是 0;列表为空时,方法一返回初始值 1,math.prod 也返回 1,reduce 则会因为没有起始值而报错。第五,元素很多或数值很大时,Python 的整数不会溢出,可以放心算。

小结 精髓是"累乘器 + 初始值 1":把求和的思路照搬过来,只改两处------运算符从加变乘、起点从 0 变 1,剩下的遍历逻辑完全一致。三种方法从手写循环到 math.prod 再到 reduce,又一次体现了 Python 由繁到简、能偷懒就用现成轮子的过程。往后遇到连乘、阶乘、累积放大这类需求,思路都是这套------准备一个初始为 1 的变量,遍历一遍逐个乘进去。

第四十一题,翻转头尾并拼接字符串:

复制代码
#定义一个函数,该函数接收一个字符串和一个整数作为参数,完成以下操作:

#1.从字符串头部截取指定长度的字符串并翻转
#2.从字符串尾部截取指定长度的字符串并翻转
#3.分别打印头部和尾部翻转后与剩余部分拼接后的新字符串

#定义函数

def rotate_and_contact(s, n):
    """
    该函数接收一个字符串和一个整数作为参数,完成以下操作:
    1.从字符串头部截取指定长度的字符串并翻转
    2.从字符串尾部截取指定长度的字符串并翻转
    3.分别打印头部和尾部翻转后与剩余部分拼接后的新字符串
    :return: None
    """

    #从字符串头部截取指定长度的字符串并翻转

    head = s[:n][::-1]

    #头部剩余部分

    head_remaining = s[n:]

    #头部翻转后与剩余部分拼接后的新字符串

    head_result = head + head_remaining

    #从字符串尾部截取指定长度的字符串并翻转

    tail = s[-n:][::-1]

    #尾部剩余部分

    tail_remaining = s[:-n]

    # 尾部翻转后与剩余部分拼接后的新字符串

    tail_result = tail + tail_remaining

    # 打印结果
    print(head_result)

    print(tail_result)

#调用函数

rotate_and_contact("hello world", 3)

以下是代码块逻辑分析:

翻转头尾并拼接字符串

题目要求:给一个字符串和一个整数 n,先从字符串头部截出前 n 个字符、翻转后再接回剩下的部分;再从尾部截出后 n 个字符、翻转后接到剩余部分前面,分别打印两个新字符串。比如 "hello world" 和 3,头部处理是把前 3 个字符 "hel" 翻转成 "leh" 再接上 "lo world",得到 "lehlo world";尾部处理是把后 3 个字符 "rld" 翻转成 "dlr" 再接上 "hello wo",得到 "dlrhello wo"。

核心思路:全靠字符串切片,一个切片负责"截取",一个负责"翻转" 这道题没有循环、没有计数器,从头到尾都是切片在干活,关键是看懂每一段切片的边界。头部:s:n 取前 n 个字符,::-1 把它整个倒过来,两段合起来 s:n::-1 就是"截取 + 翻转";剩下的部分用 sn:,从第 n 个位置一直取到末尾,两者用 + 拼成 head_result。尾部:s-n: 用负数下标取最后 n 个字符,同样 ::-1 翻转;剩余部分用 s:-n,从头取到倒数第 n 个之前,拼成 tail_result。这里最巧妙的就是负数索引-------n 表示"从末尾往前数 n 个",省去了自己算长度的麻烦。

举个例子 字符串 "hello world",n=3。头部:s:3 是 "hel",翻转成 "leh";s3: 是 "lo world",拼起来打印 "lehlo world"。尾部:s-3: 是 "rld",翻转成 "dlr";s:-3 是 "hello wo",拼起来打印 "dlrhello wo"。两行结果一前一后被打印出来。

几个细节 第一,::-1 是 Python 里翻转字符串(或列表)最地道的写法,冒号之间省略了起止,只留步长 -1,表示从后往前逐个取。第二,切片有个很好的"容错"特性:就算 n 超过字符串长度,s:n 也只会取到末尾而不会报错,但 s-n:、s:-n 在 n 过大时可能取到空串或整个串,结果会不太直观。第三,边界情况要小心 n=0:此时 s:0 是空串,s-0: 因为 -0 等于 0,会取到整个字符串,容易和预期不符。第四,函数是直接 print 而不是 return(返回 None),所以结果只能看到、不能在别处接着用;若想复用,应改成返回 head_result 和 tail_result。第五,字符串是不可变的,所有切片都是生成新串,原字符串 s 本身没有改动。

小结 精髓是"用切片代替循环":截取靠 :n 和 -n:,翻转靠 ::-1,剩余部分靠 n: 和 :-n,再用加号一拼就完成。头尾两套逻辑结构完全对称,只是把正数索引换成了负数索引。往后遇到"截取、翻转、重新拼接字符串"这类需求,思路都是这套------先想清楚每一段切片取的是哪部分,再用 ::-1 翻转、用 + 组装,比手写循环简洁得多。

第四十二题,交换字典键与值:

复制代码
# 定义一个函数,该函数接收一个字典作为参数,返回键值交换后的新字典

# 定义函数
def swap_key_value(input_dict: dict) -> dict:
    """
    交换字典的键与值
    :param input_dict: 原字典
    :return: 键值交换后的新字典
    """
    # 使用字典推导式:把原来的 value 当作新 key,原来的 key 当作新 value
    return {v: k for k, v in input_dict.items()}


# 给定字典
original_dict = {'a': 1, 'b': 2, 'c': 3}

# 调用函数并打印结果
print(swap_key_value(original_dict))   # {1: 'a', 2: 'b', 3: 'c'}

以下是代码块逻辑分析:

交换字典键与值

题目要求:给一个字典,把它的键和值对调,返回一个新字典------原来的值变成新字典的键,原来的键变成新字典的值。比如 {'a': 1, 'b': 2, 'c': 3},交换后就是 {1: 'a', 2: 'b', 3: 'c'}。

核心思路:遍历键值对,把 k、v 的位置调个个儿塞进新字典 这道题的核心就一行字典推导式 {v: k for k, v in input_dict.items()}。拆开看:input_dict.items() 把字典变成一个个 (键, 值) 对,for 循环里用 k, v 把每一对解包成两个变量,然后关键在冒号两边------正常写字典是 键: 值,也就是 {k: v},这里故意反过来写成 {v: k},让原来的值站到了键的位置、原来的键站到了值的位置,交换就在这一步悄悄完成了。整个推导式等价于"新建一个空字典,遍历每一对,把 v 当键、k 当值塞进去",只是写成了一行更紧凑的形式。函数还加了类型注解 (input_dict: dict) -> dict,明确表示收一个字典、还一个字典。

举个例子 字典是 {'a': 1, 'b': 2, 'c': 3}。items() 给出 ('a',1)、('b',2)、('c',3) 三对;第一对 k='a'、v=1,写成 1:'a';第二对写成 2:'b';第三对写成 3:'c'。三对合起来,返回 {1: 'a', 2: 'b', 3: 'c'},最后被打印出来。

几个细节 第一,也是最重要的坑------原来的值必须能当键。字典的键要求是"可哈希"的,数字、字符串、元组都行,但列表、字典这类可变对象不行,否则交换时会直接报 TypeError。第二,原来的值还不能重复。如果两个键对应同一个值,比如 {'a':1, 'b':1},交换后都指向键 1,后一个会覆盖前一个,结果只剩 {1:'b'},数据就丢了。第三,这里返回的是全新的字典,原字典 original_dict 不会被改动。第四,推导式比手写 for 循环加 resultv=k 更简洁,也是 Python 里最地道的写法。第五,如果确实存在值重复、又不想丢数据,可以把新值设成列表,用 result.setdefault(v, \[\]).append(k) 把冲突的键都收进来。

小结 精髓是"在冒号两边交换 k 和 v":借助 items() 拿到每一对键值,再用字典推导式把两者位置对调,一行就完成交换。它和前几道题一样,都是"遍历容器 + 边看边构造新结果"的套路,只是这回构造的是字典而不是累加数字。往后遇到"字典翻转""按值反查键""映射关系倒置"这类需求,思路都是这套------遍历键值对,把想要的方向重新组装成一个新字典,同时记得留意值是否可哈希、是否重复这两个前提。

以上就是今天全部的题目了。

相关推荐
程序喵大人1 小时前
【C++入门】编译链接模型 - 02 预处理把头文件怎样塞进源文件
开发语言·c++·预处理·编译链接·头文件·源文件
m0_547486661 小时前
《数据挖掘:理论、方法与实践基于Python语言》全套PPT课件2026(中国地质大学)
人工智能·python·数据挖掘
茉莉玫瑰花茶1 小时前
GO [ 并发 · 调度器 ]
开发语言·后端·golang
zhangzeyuaaa1 小时前
深入理解 Ruby 可变对象与不可变对象的原理、坑点与最佳实践
开发语言·后端·ruby
meiying88381 小时前
电商图片批量处理实战:Python+Pillow 一键完成裁剪、压缩、水印与格式转换
python·pillow
高洁011 小时前
AI视频生成技术:从静态图文到动态视觉的内容智能革命
python·深度学习·django·transformer·tornado
沐欣工作室_lvyiyi1 小时前
基于Flask的旅游大数据分析与可视化系统(论文+源码)
python·flask·旅游
施棠海1 小时前
多 Agent 团队编排系统的设计与实测:agent-workflow
python·ai·架构