当前位置: 首页 > news >正文

python 第六课 (字典 函数 None 作用域 函数嵌套 函数递归调用 重点)

字典的基本特性

1.字典(dict)是Python中用于存储键值对(key-value)的数据结构
2.键必须是不可变类型(如数字、字符串、元组
3.值可以是任意类型。字典是可变的,支持动态增删改查操作。
4.字典可以嵌套, 都可以嵌套

字典的定义方式

空字典可以通过花括号{}dict()函数创建:

d1={}d2=dict()

带初始值的字典直接使用花括号声明键值对:

d3={'张三':18,'李四':19}d4={100:150,'李四':30}

键的注意事项

1.字典的键必须是不可变类型,若使用可变类型(如列表)会报错。
2.修正方法是将可变类型转换为不可变类型(如元组):

# 错误示例:列表作为键d5={['抽烟','喝酒']:70}# 正确示例:元组作为键d6={('抽烟','喝酒'):70}

值的灵活性

字典的值可以是任意类型,包括列表、嵌套字典等:

d7={'数据计算':['武惠强','白洁']}# 值为列表

键重复的处理

当键重复时,后定义的键值会覆盖先前的值:

d8={'王五':'赵六','李四':30,'王五':'赵六'}# 若后续出现相同键,值会被覆盖

类型检查

使用type()函数可验证字典类型:

print(type(d1))# 输出:<class 'dict'>

字典基本操作总结

字典添加
通过直接赋值或update()方法添加键值对:

stu={"name":"武惠强",'age':18,"height":176.5}stu['hobby']=['抽烟','喝酒','烫头']# 直接添加stu.update({'name':'嘉禾'})# 通过update合并字典运行结果:{'name':'武惠强','age':18,'height':176.5,'hobby':['抽烟','喝酒','烫头']}{'name':'嘉禾','age':19,'height':176.5}

字典删除
使用delpop()clear()方法:

delstu["hobby"]# 删除指定键值对res=stu.pop('weight')# 删除并返回valueres2=stu.pop('id','删除失败')# 安全删除(避免报错)stu.clear()# 清空字典运行结果:160删除失败{}

字典修改
直接赋值或通过update()更新:

stu['age']=19# 直接修改stu.update({'name':'嘉禾'})# 批量更新运行结果:{'age':19}{'age':19,'name':'嘉禾'}

字典查询
通过键访问或get()方法:

res4=stu['name']# 直接访问(键不存在时报错)res5=stu.get('hobby','meiyo')# 安全访问(返回默认值)运行结果: meiyo 嘉禾

遍历字典
获取键、值或键值对:

keys=stu.keys()# 获取所有键(dict_keys类型)values=stu.values()# 获取所有值(dict_values类型)items=stu.items()# 获取键值对(dict_items类型)forkeyinstu:# 遍历键并访问值print(key,stu[key])运行结果: dict_keys(['name','age','height'])dict_values(['嘉禾',19,176.5])dict_items([('name','嘉禾'),('age',19),('height',176.5)])name 嘉禾 age19height176.5

注意事项

  • 1.直接通过键访问(如stu['key'])在键不存在时会报错,推荐使用get()方法。
  • 2.pop()可设置默认值避免报错,del无法提供默认值。
  • 3.update()可批量更新或添加键值对,适合合并字典。

函数的定义与作用

函数是用于执行特定任务的重复使用代码块,主要作用包括:

    1. 代码复用,减少重复编写相同逻辑
    1. 提升程序可读性和维护性
    1. 支持模块化开发,便于团队协作

函数的分类

  1. 内置函数:如print()type()range(),无需导入即可直接使用
  2. 模块函数:需导入模块后调用,例如random.randint()math.sqrt()
  3. 自定义函数:由开发者定义,通过def关键字声明,例如:
def函数名(形参):函数体

形参与实参的区别

  • 形参:函数定义时声明的参数,用于接收外部传入的值,作用域仅限于函数内部
  • 实参:调用函数时传递的具体值或变量

示例说明

无参函数

defwelcome():print('欢迎大家来到')welcome()# 多次调用避免重复代码

带参函数

deforder(num,dish):print(f'你点了{num}{dish}')order(7,"桃花面")# 实参为具体值

函数返回值
通过return返回结果,例如实现冒泡排序:

defbubbleSort(arr):foriinarr:forjinrange(len(arr)-1):ifarr[j]>arr[j+1]:arr[j],arr[j+1]=arr[j+1],arr[j]returnarr sorted_arr=bubbleSort([10,1,5,6,4])print(sorted_arr)

位置参数

函数调用时,参数按定义顺序传递,实参与形参一一对应。例如:

order(7,"桃花面")# 7对应num,"桃花面"对应dish

关键字参数

通过形参名直接指定实参,允许参数顺序与定义不一致。例如:

info(height=170,name='张强',gender="男",age=18)

混合使用规则

位置参数必须出现在关键字参数之前。例如:

info('董小姐',18,height=175,gender='女')

参数传递限制

  • /前的参数必须用位置参数传递
  • *后的参数必须用关键字参数传递
  • /必须位于*之前。例如:
definfor(name,/,age,*,gender,height):print(f"我是{name},我今年{age}岁,我是{gender}生,我的升高是{height}")infor('sb',18,height=175,gender='女')

默认参数

形参可设置默认值,调用时未传递则使用默认值。例如:

definfor2(name,/,age,*,gender,height,msg='默认消息'):...infor2('sb',18,height=175,gender='女')# 使用默认msg

可变位置参数(*args)的特点

调用函数时,所有未命名的位置参数会被收集到一个元组中,通过args访问。test1('张强',18,'男',170)的输出显示args是一个包含所有额外位置参数的元组。

可变关键字参数(**kwargs)的特点

调用函数时,所有未命名的关键字参数会被收集到一个字典中,通过kwargs访问。test2(name='阿涛',age=20,height=170)的输出显示kwargs是一个包含所有额外关键字参数的字典。

参数顺序的注意事项

当函数定义中包含位置参数、默认参数、可变位置参数和可变关键字参数时,必须严格按照以下顺序声明:

  1. 普通位置参数(如a,b
  2. 默认参数(如c='我是'
  3. 可变位置参数(*args
  4. 可变关键字参数(**kwargs

默认参数的位置影响

当默认参数放在可变位置参数之前(如def test3(a,b,c='我是',*args,**kwargs)),调用时'chou'会被赋值给c,后续参数进入args元组。

当默认参数放在可变位置参数之后(如def test3(a,b,*args,c='我是',**kwargs)),必须通过关键字显式指定c的值,否则会被args捕获。

代码执行结果差异

第一种定义方式下test3('张三','娜','chou','hejiu','tangtou',age='18')会将'chou'作为默认参数c的值。
第二种定义方式下相同调用会将'chou'作为args的一部分,而c保持默认值'我是'

None 的特性总结

None 是 Python 中表示空值或无意义的特殊常量,属于NoneType类型。
在条件判断中,None 会被视为False
None 不能参与数学运算或字符串拼接操作。
函数默认返回值为 None,除非显式使用return指定返回值。

空值与 False 的等价性示例

以下值在条件判断中会被视为False

  • 空字符串''
  • 数字0
  • 布尔值False
  • 空列表[]
  • None

函数返回值规则

函数若不设置return语句,默认返回None
使用return时:

  • return后的表达式作为函数返回值
  • return会立即终止函数执行,后续代码不再运行

示例:

defadd(a,b):returna+b# 返回两数之和result=add(10,20)# 结果为30

作用域的定义与分类

作用域指变量在程序中可被访问的范围,分为全局作用域和局部作用域。
1.全局作用域变量在整个程序中有效。
2.局部作用域变量仅在函数或代码块内有效。

全局作用域与局部作用域的特点

全局变量

a=100b=200deftest():# 局部变量c='你好'd='python'# 声明使用全局变量aglobala# 修改全局变量a的值a=30# 函数内打印变量print('函数a:',a)# 输出:函数a: 30print('函数b:',b)# 输出:函数b: 200(访问全局变量b)print('函数c:',c)# 输出:函数c: 你好(访问局部变量c)print('函数d:',d)# 输出:函数d: python(访问局部变量d)# 调用函数test()# 全局作用域打印变量print('全局打印a',a)# 输出:全局打印a 30(已被函数修改)print('全局打印b',b)# 输出:全局打印b 200# print(c) # 这行会报错:NameError: name 'c' is not defined(c是函数内局部变量,外部无法访问)
  • 定义在函数外部,整个程序均可访问。
  • 生命周期从程序开始到结束。
  • 示例:a = 100b = 200

局部变量

  • 定义在函数内部,仅函数内可访问。
  • 生命周期从函数调用开始到函数执行结束。
  • 示例:c = '你好'd = 'python'

使用global关键字

通过global可将局部变量声明为全局变量,或在函数内修改全局变量:

globala# 声明使用全局变量aa=30# 修改全局变量a的值

作用域的生命周期

  • 局部变量:函数调用时创建,执行完毕后销毁。多次调用函数时,每次都会重新创建局部变量(如mtest3()中每次初始化为100)。
deftest3():m=100m+=1print(f'我是函数中的m为{m}')test3()test3()test3()test3()运行结果为: 我是函数中的m为101我是函数中的m为101我是函数中的m为101我是函数中的m为101
  • 全局变量:程序启动时创建,结束时销毁。函数内修改后全局生效(如y通过global声明后累加)。
y=100deftest3():globaly y+=1print(f'我是函数中的y为{y}')test3()test3()test3()运行结果为: 我是函数中的y为101我是函数中的y为102我是函数中的y为103

注意事项

  • 未使用global时,函数内赋值会默认创建局部变量。
  • 尝试在全局访问局部变量会引发NameError(如print(c))。
  • 循环结构(如while)不形成独立作用域,其内部变量遵循所在函数或全局的作用域规则。

函数嵌套的基本概念

函数嵌套指的是在一个函数的执行过程中调用另一个函数。这种调用可以是直接的,也可以是间接的(通过多层调用)。

示例分析

示例1:直接嵌套调用

defone(name,msg):print(f'我叫{name},我想说{msg}')two(msg)print('one函数结束了')deftwo(msg):print('*********')print(msg)print('*********')one("小明","很高兴认识你")运行结果为: 我叫小明,我想说很高兴认识你*********很高兴认识你*********one函数结束了
  • 函数one在内部调用了函数two,并将参数msg传递给two
  • 调用顺序:one->two-> 返回one继续执行剩余代码。

示例2:多层嵌套调用

deftest1():print('进入test1')test2()print('退出test1')deftest2():print('进入test2')test3()print('退出test2')deftest3():print('进入test3')print('执行函数33333333')print('退出test3')test1()运行结果为: 进入test1 进入test2 进入test3 执行函数33333333退出test3 退出test2 退出test1
  • 函数test1调用test2test2又调用test3
  • 调用顺序:test1->test2->test3-> 返回test2-> 返回test1

嵌套调用的特点

  1. 执行流程:嵌套调用遵循“先进后出”的原则,类似于栈结构。被调用的函数执行完毕后,控制权会返回到调用它的函数。
  2. 参数传递:调用时可以通过参数将数据传递给被调用的函数。
  3. 代码复用:通过嵌套调用,可以避免重复编写相同的逻辑,提高代码复用性。
  4. 调试复杂性:多层嵌套可能导致调试困难,需注意调用链的清晰性。

注意事项

  • 避免无限递归:如果函数间接或直接调用自身,可能导致无限递归。
  • 控制嵌套深度:过深的嵌套会降低代码可读性,建议合理拆分函数。

递归调用的基本概念

递归调用指的是函数在执行过程中直接或间接调用自身的操作。递归通常包含两个关键部分:基线条件(终止条件)和递归条件(继续调用自身的条件)。

递归示例分析

以下代码展示了一个简单的递归函数,打印多次"你好呀":

defhello(n):print(f'你好呀{n}')ifn>1:hello(n-1)hello(5)运行结果为: 你好呀5你好呀4你好呀3你好呀2你好呀1

递归的执行顺序

递归的执行顺序取决于递归调用与操作的位置关系。以下代码展示了操作在递归调用后的执行顺序:

defhello(n):ifn>1:hello(n-1)print(f'你好呀{n}')hello(5)运行结果为: 你好呀1你好呀2你好呀3你好呀4你好呀5

递归与嵌套调用的等价性

递归可以被理解为一种嵌套调用的简化形式。以下代码展示了递归与手动嵌套调用的等价性:

defhello1():print(f'你好呀1')defhello2():hello1()print(f'你好呀2')defhello3():hello2()print(f'你好呀3')defhello4():hello3()print(f'你好呀4')defhello5():hello4()print(f'你好呀5')hello5()

文档字符串(函数注释)

示例
以下是一个简单的求和函数示例:

defadd(a,b):"""这是一个求和函数"""# 文档字符串returna+b add(10,20)

递归的关键要点

递归必须包含明确的终止条件,否则会导致无限递归。递归的执行过程会形成调用栈,每次递归调用都会将当前状态压入栈中,直到满足终止条件才开始回溯执行。

递归可以简化代码结构,但需要注意栈溢出风险和性能问题。对于复杂问题,递归通常比循环更简洁直观,但在性能敏感场景可能需要考虑尾递归优化或改用迭代实现。

http://www.jsqmd.com/news/542198/

相关文章:

  • 3步掌握高效视频处理:ffmpegGUI让复杂命令可视化
  • 高效掌握BBDown:全场景哔哩哔哩视频下载工具使用指南
  • AutoDock Vina分子对接中过渡金属原子类型处理的5种突破性策略:高级技术架构指南
  • Switch-Toolbox:如何破解任天堂游戏文件编辑的三大技术难题?
  • 别再只调API了!用Java手搓一个能“思考”和“行动”的AI Agent(附完整代码)
  • 同步异步通信:UART详解
  • 3个步骤极速部署AdGuard广告拦截扩展:跨浏览器零门槛配置指南
  • 解锁compressorjs的图像优化能力:打造高性能Web应用的前端图片处理方案
  • E820 内存映射表深度解析
  • Elasticsearch 7.x 安全加固实战:从裸奔到密码保护的完整配置指南
  • Hearthstone-Script终极指南:如何免费自动化你的炉石传说游戏体验
  • 2026年质量好的企业oa系统/oa办公管理平台热门公司推荐 - 品牌宣传支持者
  • LFM2.5-1.2B-Thinking-GGUF参数详解:max_tokens/temperature/top_p调优实战
  • 从Fastjson到OGNL:JSONPath与表达式语言的性能对比与选型建议
  • 包装器简介
  • X-TRACK二次开发终极指南:如何基于开源框架快速扩展新功能
  • OpenClaw定时任务:百川2-13B实现每日早报自动生成与发送
  • vLLM-v0.17.1入门必看:WebShell交互式调试LLM推理全流程
  • 真空贴体包装机哪家好?2026海产品气调包装厂家优选,实力品牌,护航保鲜全链路 - 栗子测评
  • ViGEmBus如何解决Windows游戏控制器兼容性难题?
  • 2026年热门的oa品牌公司推荐 - 品牌宣传支持者
  • 《CAN机能》开发全流程实战指南
  • Simulink与Plecs联合仿真实现三相桥式电路能量双向流动
  • 6种压缩黑科技如何彻底解决文件处理的效率难题
  • League Akari:5大核心解决方案提升英雄联盟游戏体验
  • 不换硬件,速度翻倍:本地 LLM 推理加速实战
  • 链表合并不解之处
  • 百川2-13B-4bits模型调优指南:提升OpenClaw任务执行准确率
  • 文艺复兴,什么是XSS,常见形式(二)
  • FreeRTOS任务跑飞了?结合STM32 HardFault信息,深度排查任务栈溢出与内存踩踏