Python 入门必吃透:函数、列表与元组核心用法(附实战案例)

Python 入门必吃透:函数、列表与元组核心用法(附实战案例)
在这里插入图片描述

🔥草莓熊Lotso:个人主页
❄️个人专栏: 《C++知识分享》《Linux 入门到实践:零基础也能懂》
✨生活是默默的坚持,毅力是永久的享受!


🎬 博主简介:

在这里插入图片描述

文章目录


前言:

作为 Python 初学者,掌握函数列表元组是从 “写代码” 到 “写好代码” 的关键一步。它们不仅是 Python 语法的核心,更是后续处理复杂数据、构建高效程序的基础。今天这篇文章,就结合入门实战案例,把这三个知识点讲透,新手也能一看就会、一用就通。

一. 函数:告别重复代码的 “代码工厂”

1.1 为什么需要函数?

写代码最忌讳的就是 “复制粘贴”。比如计算不同区间的数列和(1-100、300-400、1-1000),如果不使用函数,需要重复写多组几乎一样的循环代码:

# 1. 计算 1-100 的和 theSum =0for i inrange(1,101): theSum = theSum + i print(theSum)# 2. 计算 300-400 的求和 theSum =0for i inrange(300,401): theSum = theSum + i print(theSum)# 计算 1-1000 的和 theSum =0for i inrange(1,1001): theSum = theSum + i print(theSum)

一旦需要修改计算逻辑(比如改成求平方和),所有重复代码都要改,效率极低。而函数的核心作用,就是提取重复代码,实现代码复用,让程序更简洁、更好维护。

简单理解:函数就像一个 “工厂”,输入 “原材料”(参数),经过内部加工(函数体),输出 “产品”(返回值),一次定义,多次调用。

函数版本代码

# 使用函数的方式来解决刚刚的问题# 定义一个求和函数defcalcSum(begin,end): theSum =0for i inrange(begin,end+1): theSum = theSum + i print(theSum)# 使用函数# 求 1-100 的和 calcSum(1,100)# 求 300-400 的和 calcSum(300,400)# 求 1-1000 的和 calcSum(1,1000)
在这里插入图片描述

1.2 函数的核心语法(重点)

(1)函数定义与调用

# 1. 定义函数:def 函数名(形参列表): 函数体 return 返回值defcalcsum(beg, end):# beg、end是“形式参数”(形参),相当于工厂的“原材料入口”sum=0for i inrange(beg, end +1):sum+= i returnsum# return 输出结果,相当于工厂的“产品出口”# 2. 调用函数:函数名(实参列表) result1 = calcsum(1,100)# 1、100是“实际参数”(实参),是真正传入的原材料 result2 = calcsum(300,400)print(result1, result2)# 输出:5050 35150
deftest(a,b,c):print(a,b,c)# 实参个数不能多也不能少,除非形参有默认参数 test(10,20,30)

⚠️ 关键注意点

  • 函数必须先定义,再调用(就像动漫里“先喊招式名,再释放技能”),否则会报 NameError
  • 定义函数时不会执行函数体,只要调用时才会执行,调用几次就执行几次;
  • 形参和实参的个数必须匹配(比如定义时 2 个形参,调用时就必须传 2 个实参),否则报 TypeError

(2) 函数参数的灵活用法
Python 的函数参数比C++,Java更灵活,核心有 3 个特性:

1. 动态类型:形参无需指定类型,一个函数可接收多种类型参数

defprint_param(a):print(a) print_param(10)# 整数 print_param("hello")# 字符串 print_param(True)# 布尔值(均能正常执行)
defadd(x,y):return x+y print(add(10,20))print(add(1.5,2.5))print(add('hello','world'))# # 这个就肯定不行了.不符合函数体内执行逻辑# print(add(10,'hello'))

2. 参数默认值:给形参指针默认值,调用时可省略该参数(默认值参数必须在无默认值参数后面)

# 计算两数之和,默认不打印调试信息defadd(x, y, debug=False):if debug:print(f"调试:x={x}, y={y}")return x + y print(add(10,20))# 省略debug,使用默认值Falseprint(add(10,20,True))# 显式传参,打印调试信息

3. 关键字参数:调用时显示指定“实参对应哪个形参”,可打乱传参顺序

deftest(x,y):print(f"x = {x}")print(f"y = {y}")# 关键字参数,顺序无关,输出: x = 10,y = 20; test(x =10,y =20) test(y =100,x =200) test(100,y =200)# 这样写就不行了# test(x = 100,200)

(3) 函数返回值
返回值是函数的 “输出”,核心用法有两点:

1. 一个函数可以有多个 return 语句,执行到 return 时函数立刻结束(后续代码不执行)

# 这种情况不算是有多个 return 语句# def tes():# return 1# return 2# 一般情况下多个 return 语句是搭配 分支语句/循环语句 的# 用来判断 num 是不是奇数defisOdd(num):if num %2==0:returnFalseelse:returnTrueprint(isOdd(10))print(isOdd(19))

2. 一次返回多个值:用逗号分隔,接收时用多个变量接收(无需接收的用 _ 忽略)

# 写一个函数, 返回平面上的一个点# 横坐标,纵坐标defgetPoint(): x =10 y =20return x,y # 可以返回两个值# a,b = getPoint() # 接收所有返回值# 如果只想用其中一个可以使用 _ 占位# _,b=getPoint() # 忽略x,只接收y

(4) 变量作用域

变量的作用域决定了 “变量能在哪些地方使用”,核心规则:

  • 局部变量:函数内部定义的变量,仅在函数内部生效(出了函数就失效);
  • 全局变量:函数外部定义的变量,函数内部可访问,但 修改时需要用global 声明;
  • 同名变量:不同作用域可存在同名变量(本质是不同变量,互不影响)
x =10deftest(): x =20print(f'函数内部:{x}') test()print(f'函数外部:{x}')
x =10# 全局变量在函数里也可以使用# def test():# print(f'x = {x}')## test()# 使用这个函数,把全局变量 x 给改成 20!deftest():global x x =20 test()print(f'x = {x}')

1.3 函数的进阶用法(嵌套 + 递归)

(1)链式调用:把一个函数的返回值,作为另一个函数的参数

defisOdd(num):if num %2==0:returnFalsereturnTruedefadd(x,y):return x+y # result = isOdd(10)# print(result)#print(isOdd((add(5,5))))

(2)嵌套调用:函数内部调用其他函数(包括自身)

deftest():print("hello") test()# 嵌套调用可以有很多层defa(): num =10print("函数 a")defb(): num =20 a()print("函数 b")defc(): num =30 b()print("函数 c")defd(): num =40 c()print("函数 d") d()

函数之间的调用关系,在Python中会使用一个特定的数据结构来表示,称为 函数调用栈,每次函数调用,都会在调用栈里新增一个元素,称为 栈帧

  • 可以通过 PyCharm 调试器看到函数调用栈和栈帧。
  • 在调试状态下,PyCharm 左下角一般就会显示出函数调用栈。
在这里插入图片描述


在这里插入图片描述

选择不同的栈帧,可以看到各自栈帧中的局部变量。

思考:上述代码,a,b,c,d 函数中的局部变量名各不相同,如果变量名是相同的,比如都是 num,那么这四个函数中的 num 是属于同一个变量,还是不同变量呢? – 不同变量

(3)递归调用:函数调用自身(慎用!)

递归是嵌套调用的特使情况,核心是"有结束条件 + 每次逼近结束条件",否则会无限递归导致 RecursionError

案例:递归计算 5 的阶乘 (5! = 5 * 4 * 3 * 2 * 1)

# 写一个函数,来求 n 的阶乘(n是正整数)# def factor(n):# result = 1# for i in range(1,n+1):# result *= i# return result# 递归# n! => n * (n-1)!# 1! => 1deffactor(n):if n ==1:return1return n * factor(n -1)print(factor(5))
  • 务必存在递归结束条件,比如 if n == 1 就是结束条件。当 n 为 1 的时候,递归就结束了。
  • 每次递归的时候,要保证函数的实参是逐渐逼近结束条件的。

⚠️ 注意:递归代码简洁但难理解,易栈溢出,实际开发中优先用循环替代。

1.4 函数核心小结

掌握 3 点,搞定 Python 函数:

  • 定义def 函数名(形参):函数体 return 返回值
  • 调用:函数名(实参),支持默认值,关键字参数;
  • 核心价值:复用代码,拆分逻辑,让程序更容易维护。

二. 列表和元组:批量存储数据的 “容器”

当需要存储多个数据(比如10个学生的成绩,20个城市名)时,单独定义多个变量不现实,此时就需要列表(list)和元组(tuple)—— 它们是 Python 中最常用的 “序列类型”,专门用来批量存储数据。

核心区别(一句话记牢):

  • 列表(list):可变容器(像 “散装辣条”),元素可增删改;
  • 元组(tuple):不可变容器(像 “包装辣条”),元素创建后无法修改。

2.1 列表(list):最常用的可变容器

(1)创建列表

两种核心方式,推荐用 [ ] (更简洁)

# 创建列表# 1. 直接使用字面值来创建# [] 就表示一个 空的列表 a =[]print(type(a))# 2. 使用 list() 来创建 b =list()print(type(b))# 3. 可以在创建列表的时候,在[]中指定列表的初始值# 元素之间使用 , 来分割 a =[1,2,3,4]print(a)# 4. 可以在同一个列表里放不同类型的变量 a =[1,'hello',True,[4,5,6]]print(a)

⚠️ 注意:不要用 list 作为变量名(会覆盖内置函数 list()),建议命名为 list1,alist 等。

(2)列表的核心操作(必练)

列表的操作都围绕 “下标” 展开,下标从 0 开始(负数表示倒数,-1 是最后一个元素),核心操作如下:

操作目的代码示例说明
访问元素list3[2]访问下标 2 的元素(list3 [2] = 3),下标越界报 IndexError
修改元素list3[2] = 100把下标 2 的元素改成 100,list3 变成 [1,2,100,4]
切片(取子列表)list3[1:3]取下标 1 到 3(左闭右开)的元素,输出 [2,100]
新增元素list3.append(5)尾插(添加到末尾);list3.insert(1, "a")(插入到下标 1)
删除元素list3.pop()删除末尾元素;list3.pop(2)(删除下标 2 元素);list3.remove(2)(按值删除)
查找元素2 in list3判断元素是否存在(返回布尔值);list3.index(2)(找下标,不存在报异常)
连接列表list3 + list4拼接两个列表(生成新列表);list3.extend(list4)(拼接到 list3 末尾,修改原列表)
遍历元素for elem in list3:直接遍历元素(推荐);也可按下标遍历(for i in range(len(list3))
  • 下标访问
# 5. 使用下标来访问列表元素 a =[1,2,3,4]print(a[2])# 3# 6. 使用下标来修改列表元素 a =[1,2,3,4] a[2]=100print(a)# 7. 超出下标有效范围,就会出现异常# a = [1,2,3,4]# a[100] = 0# print(a)# Traceback (most recent call last):# File "D:\Gitee.code\python-fundamentals-\PythonProject\2025--11--24\code42.py", line 33, in <module># a[100] = 0# ~^^^^^# IndexError: list assignment index out of range# 8. 可以使用内建函数 len 来获取列表的长度(元素个数),和字符串类似 a =[1,2,3,4]print(len(a))# 9. Python 中的下标,其实还可以写成负数!!!# 例如写成 -1,其实等价于 len(a) - 1 a =[1,2,3,4]print(a[len(a)-1])# -1 就是倒数第一个元素print(a[-1])
  • 循环遍历
# 1. 使用 for 循环来遍历列表# 不会改变原来的数组# a = [1,2,3,4,5]# for elem in a:# elem = elem + 10# print(elem)# print(a)# 2. 使用 for 循环遍历,通过下标的方式# 会改变原来的数组# a = [1,2,3,4,5]# for i in range(0,len(a)):# a[i] = a[i] + 10## print(a)# 3. 使用 while 循环,通过下标遍历这个列表 a =[1,2,3,4,5] i =0while i <len(a):print(a[i]) i +=1
  • 增删查改 && 连接等
# 1. 使用 append 往列表末尾新增一个元素# a = [1,2,3,4]# a.append(5)# a.append("hello")# print(a)# b = [5,6,7,8]# b.append("world")# print(b)# 2. 还可以使用 insert 方法,往列表的任意位置来新增元素 a =[1,2,3,4] a.insert(1,"hello") a.insert(100,"hello")# 会在最后插入一个 helloprint(a)
# 1. 使用 in 来判定某个元素是否在列表中存在# a = [1,2,3,4]# print(1 in a)# print(10 in a)# print(1 not in a)# print(10 not in a)# 2. 使用 index 方法,来判定当前元素在列表中的位置,得到一个下标 a =[1,2,3,4]print(a.index(2))print(a.index(3))# print(a.index(10)) # 会报错
# 1. 使用 pop 删除列表中的最末尾的元素 a =[1,2,3,4] a.pop()print(a)# 2. 使用 pop 还能删除任意位置的元素,pop的参数 a =[1,2,3,4] a.pop(1)print(a)# 3. 使用 remove 方法,可以按照值来进行删除 a =["aa","bb","cc","dd"] a.remove("cc")print(a)
# 1. 使用 + 针对两个列表进行拼接# a = [1,2,3,4]# b = [5,6,7,8]# c = b + a# print(c)# c = a + b# print(c)# print(a)# print(b)# 2. 使用 extend 来进行拼接# 这个拼接是把后一个列表的内容拼接到前一个列表里头# a = [1,2,3,4]# b = [5,6,7,8]# c = a.extend(b) # extend 不返回任何内容# a.extend(b)# print(a) # a 这里改变了# print(b)# 3. 使用 += 来进行拼接 a =[1,2,3,4] b =[5,6,7,8] a += b # a = a + bprint(a)print(b)

(3)切片操作的灵活用法(重点)

切片是列表的 “灵魂操作”,支持省略边界、指定步长(正数从左到右,负数从右到左):

# 1. 切片操作的基本使用 a =[1,2,3,4]# 左闭右开区间print(a[1:3])# 2. 使用切片的时候,可以省略边界 a =[1,2,3,4]# 省略右边界,意思是从指定的开始位置,一直取到整个列表结束print(a[1:])# 省略左边界,意思是从列表的 0 号元素开始取,一直取到指定的结束位置print(a[:2])# 此处切边中的下标也可以写成负数print(a[:-1])# 还可以把开始边界和结束边界都省掉,得到的就还是列表本身print(a[:])# 3. 带有步长的切片操作 a =[1,2,3,4,5,6,7,8,9,0]print(a[::1])print(a[::2])print(a[::3])print(a[1:-1:2])# 4. 步长的数值还可以是负数,当步长为负数的时候,意思是从后往前来取元素 a =[1,2,3,4,5,6,7,8,9,0]print(a[::-1])print(a[::-2])# 5. 当切片中的范围超出有效下标之后,不会出现异常!,而是尽可能的把符合要求的元素给获取到 a =[1,2,3,4,5,6,7,8,9,0]print(a[1:100])

2.2 元组(tuple):不可变的序列容器

元组的用法和列表几乎一致,但核心区别是"不可变"(元素无法增删改),适合存储不需要修改的数据(比如身份证号,坐标)。

(1)创建元组

()表示,空元组用()tuple(),注意单个元素的元组要加逗号(避免被当作普通括号):

# 1. 创建元组 a =()print(type(a)) b =tuple()print(type(b))# 2. 创建元组的时候,指定初始值 a =(1,2,3,4)print(a)# 3. 元组中的元素也可以是任意类型的 a =(1,2,'hello',True,[])print(a)

(2)元组的核心操作

  • 支持的操作(和列表一致):访问下标、切片、遍历、in判断、index查找、+拼接;
  • 不支持的操作(因为不可变):修改元素、append/insert/pop/remove/extend
# 4. 通过下标来访问元组中的元素,下标也是从 0 开始,到 len - 1 结束 a =(1,2,3,4)print(a[1])print(a[-1])# print(a[100]) # 错误# 5. 通过切片来获取元组的一部分 a =[1,2,3,4]print(a[1:3])# 6. 也同样可以使用 for 循环等方式来进行遍历元素 a =(1,2,3,4)for elem in a:print(elem)# 7. 可以使用 in 来判断元素是否存在,使用 index 查找元素的下标 a =(1,2,3,4)print(3in a)print(a.index(3))# 8. 可以使用 + 来拼接两个元组 a =(1,2,3) b =(4,5,6)print(a + b)# 9. 元组只支持 “读” 操作,不能支持 “修改” 操作 a =(1,2,3,4)# 不支持以下修改的操作# a[0] = 100# a.append(5)# a.pop()# a.extend()# 10. 当进行多元赋值的时候,其实本质上是按照元组的方式来进行工作的,defgetPoint(): x =10 y =20return x,y x,y = getPoint()print(type(getPoint()))

(3)为什么有了列表,还需要元组?

  • 安全性: 传递数据时,用元组可避免数据被意外修改(比如传给一个未知函数,元组更安全);
  • 可作为字典的键: 后续要学的字典,键必须是 “可哈希对象”(不可变类型),元组可以,列表不行。

补充

在这里插入图片描述

2.3 列表的元组小结

特性列表(list)元组(tuple)
定义方式[]list()()tuple()
是否可变可变(增删改)不可变(无增删改)
适用场景需频繁修改数据(比如学生成绩)数据无需修改(比如身份证号)
核心操作支持所有序列操作 + 增删改仅支持读操作,无写操作
  • 列表和元组都是日常开发中最常用到的类型,最核心的操作就是根据 [ ] 来按下标操作。
  • 在需要表示一个 “序列” 的场景下,就可以考虑使用列表和元组。
  • 如果元素不需要改变,则优先考虑元组。
  • 如果元素需要改变,则优先考虑列表。

结尾:

🍓 我是草莓熊 Lotso!若这篇技术干货帮你打通了学习中的卡点: 👀 【关注】跟我一起深耕技术领域,从基础到进阶,见证每一次成长 ❤️ 【点赞】让优质内容被更多人看见,让知识传递更有力量 ⭐ 【收藏】把核心知识点、实战技巧存好,需要时直接查、随时用 💬 【评论】分享你的经验或疑问(比如曾踩过的技术坑?),一起交流避坑 🗳️ 【投票】用你的选择助力社区内容方向,告诉大家哪个技术点最该重点拆解 技术之路难免有困惑,但同行的人会让前进更有方向~愿我们都能在自己专注的领域里,一步步靠近心中的技术目标! 

结语:不知不觉这篇 Python 相关的分享就到尾声啦~ 作为一门灵活又实用的语言,Python 的魅力从来都藏在 “上手易、场景广” 里 —— 不管是入门时的语法摸索,还是实战中的问题拆解,每一次代码跑通的瞬间,都是对 “实践出真知” 的最好印证。如果这篇内容帮你理清了某个知识点,或是给你的项目开发带来了一点启发,欢迎在评论区交流你的心得或疑问~ 后续会持续分享 Python 进阶技巧、实战案例等干货,从基础夯实到场景落地,陪大家一起在编程路上少踩坑、多收获!
编程之路漫漫,但热爱可抵岁月漫长~ 咱们下篇博客见!

✨把这些内容吃透超牛的!放松下吧✨ʕ˘ᴥ˘ʔづきらど

Read more

OpenClaw接入模型并基于WebUI完成智能操作

OpenClaw接入自定义模型并基于WebUI完成智能操作 背景介绍 OpenClaw(原 Clawdbot)是一个开源的 AI 代理框架,支持通过配置文件或 GUI 界面进行灵活配置。安装 OpenClaw 后,用户可以通过修改工作目录下的配置文件 openclaw.json 来接入不同的 LLM 模型提供商。 OpenClaw 支持众多主流模型提供商,包括 OpenAI、Anthropic、Moonshot AI(Kimi)、OpenRouter、Vercel AI Gateway、Amazon Bedrock 等。完整的提供商目录可参考官方文档 模型提供商快速入门。 要使用自定义的提供商,需要通过 models.providers 配置进行设置。这种方式允许用户接入官方支持列表之外的其他兼容 OpenAI API 或 Anthropic 格式的模型服务。 接入配置说明 核心配置参数解析

By Ne0inhk
【算法详解】理解KMP,真的那么难吗?—— 一篇讲透它的核心思想

【算法详解】理解KMP,真的那么难吗?—— 一篇讲透它的核心思想

🫧 励志不掉头发的内向程序员:个人主页  ✨️ 个人专栏: 《C++语言》《Linux学习》 🌅偶尔悲伤,偶尔被幸福所完善 👓️博主简介: 文章目录 * 前言 * 一、相关概念 * 二、前缀函数 * 三、计算前缀函数 * 四、用前缀函数解决字符串匹配 * 五、kmp 算法模板 * 六、next 数组版本 * 七、周期和循环节 * 总结 前言 本文用尽量详细的语言来讲解说明 kmp 算法内容,学习之前需要知道一点点动态规划的基础,如果不知道最好去了解了解。我们一起来看看算法吧。 一、相关概念 在学习 kmp 算法之前,我们得先提前了解最基本的 “ 动态规划 ” 的知识,否则可能学习的时候会有一些困难,因为它的原理类似于动态规划。 字符串: * 用字符构成的的序列就是字符串。 这个概念很简单,但是我们这里有个小技巧:就和动态规划那样,

By Ne0inhk

Chromium WebRTC 在 AI 辅助开发中的实战优化与避坑指南

最近在做一个AI辅助的实时协作项目,用到了Chromium的WebRTC模块来处理音视频通信。项目上线初期,当AI推理任务(比如实时背景虚化、手势识别)和WebRTC的编解码、传输同时进行时,延迟抖动非常明显,GPU也经常被“打满”,用户体验很糟糕。这促使我深入研究了WebRTC的底层,并尝试用AI的思路去优化它,最终将端到端延迟降低了近30%。这里把整个实战优化过程和踩过的坑记录下来,希望能给遇到类似问题的朋友一些参考。 1. 背景痛点:当WebRTC遇上AI推理 在传统的视频会议场景中,WebRTC的自适应码率(GCC算法)和抗丢包(NACK、FEC)机制已经相当成熟。然而,在AI辅助开发场景下,比如实时虚拟背景、语音降噪、内容审核等,情况变得复杂很多: * 实时性要求更高:AI处理本身需要时间(推理延迟),这直接叠加在了视频采集、编码、传输、解码、渲染的链路上。用户能明显感觉到“说话”和“画面/效果响应”之间的迟滞。 * GPU资源竞争白热化:WebRTC的视频编码(特别是硬件编码)

By Ne0inhk

Qwen3-32B+Clawdbot惊艳效果展示:多轮上下文Web对话实测作品集

Qwen3-32B+Clawdbot惊艳效果展示:多轮上下文Web对话实测作品集 1. 这不是普通聊天,是真正“记得住话”的AI对话体验 你有没有试过和一个AI聊着聊着,它突然忘了你三句话前说的关键信息?或者刚让你提供产品参数,转头就问“你刚才说的产品是什么”?这种断裂感,让很多所谓“智能对话”停留在“高级复读机”阶段。 而这次实测的 Qwen3-32B + Clawdbot 组合,彻底打破了这个瓶颈。它不是在模拟理解,而是真正在维持、推理、调用长达20轮以上的上下文记忆——而且是在纯Web界面里,不装插件、不配环境、打开浏览器就能用。 我们没做任何提示词工程优化,没加特殊system message,也没调温度或top-p参数。就是像你平时和同事聊天一样:发问、补充、纠正、追问、切换话题……它全都接得住,还接得稳。 下面这12个真实对话案例,全部来自同一套部署环境下的连续实测记录,未经剪辑、未重试、未人工干预。你可以把它看作一份“

By Ne0inhk