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

Python | 第八章 | 数据容器

P70 函数的传参机制 2024/9/1

一、传参机制

函数的传参机制对我们今后的编程非常重要,一定要搞的清清楚楚明明白白,我们通过案例来学习

  • 字符串和数值类型的传参机制
    • 1)看一个案例,分析结果是什么?[可以得出函数中开辟新栈并不会影响主栈]
# @Author :zjc
# @File   :05_string_num_type_convey.py
# Time    :2024/9/1 17:17# 定义函数f1
def f1(a):print(f"f1() a的值:{a}地址是:{id(a)}")a += 1print(f"f1() a的值:{a}地址是:{id(a)}")# 定义变量a = 10
a= 10
print(f"调用f1()前a的值: {a}地址是:{id(a)}")
f1(a)
print(f"调用f1()后a的值:{a}地址是:{id(a)}")

image-20240901175937948

  • 内存分析图

image-20240901180020529

  • 字符串同样如此
# 定义函数F2
def f2(name):print(f"F2() name的值: {name}地址是:{id(name)}")name += " hi"print(f"f2() name的值: {name}地址是:{id(name)}")print("-------------")
name = "tom"
print(f"调用f2()前name的值:{name}地址是:{id(name)}")
f2(name)
print(f"调用f2()后name的值: {name}地址是: {id(name)}")

image-20240901181451521

二、结论

  • 字符串和数值类型是不可变数据类型[值改变,地址改变],当对应的变量的值发生了变化时,它对应的内存地址会发生改变

  • 可变数据类型就是:值改变,而地址不改变。

P71 递归机制 2024/9/2

一、基本介绍

1、简单的说:递归就是函数自己调用自己,每次调用时传入不同的值

2、递归有助于编程者解决复杂问题,同时可以让代码变得简洁

  • 递归解决的案例

image-20240902115343770

  • 递归举例1
# 当执行test(4),输出什么?
def test(n):if n > 2:# test(n - 1)print("n=", n)  # 执行test(4)

内存图

image-20240902141045884

递归举例2

  • 阶层问题…
# 阶乘,当执行factorial(4),返回值是多少?
def factorial(n):if n == 1:return 1else:return factorial(n - 1) * n
# 执行
print(factorial(4))
  • 内存图

image-20240902142044840

二、递归重要规则

  1. 执行一个函数时,就创建一个新的空间(栈空间)

  2. 函数的变量是独立的,比如n变量

  3. 递归必须向退出递归的条件逼近,否则就是无限递归,就会出现 RecursionError: maximum recursiondepth exceeded【死龟了:)】

  4. 当一个函数执行完毕,或者遇到return,就会返回,遵守谁调用,就将结果返回给谁

P72 递归练习 2024/9/2

一、题目练习

  1. 请使用递归的方式求出斐波那契数1,1,2,3,5,8,13…给你一个整数n,求出它的值是多。
# @Author :zjc
# @File   :07_function_recursion_exercise.py
# Time    :2024/9/2 16:12# 请使用递归的方式求出斐波那契数1,1,2,3,5,8,13...给你一个整数n,求出它的值是多。
def fbn(n):"""功能:返回n对应的斐波那契数:param n:接受一个整数 n => 1:return:返回裴波那契数"""if n == 1 or n == 2:return 1# 如果n>2则对应的裴波那契数为 n-1和n-2对应的裴波那契数的和else:return fbn(n - 1) + fbn(n - 2)# 完成测试
print(fbn(3))
  1. 猴子吃桃子问题:有一堆桃子,猴子第一天吃了其中的一半,并再多吃了一个!以后每天猴子都吃其中的一半,然后再多吃一个。当到第10天时,想再吃时(即还没吃),发现只有1个桃子了。问题:最初共多少个桃子?
# @Author :zjc
# @File   :08_recursion_exercise_02.py
# Time    :2024/9/2 16:26"""思路分析:1. day ==10 ,桃子数 = 12. day == 9 桃子数 == (day10+1)*23. day == 8 桃子数 == (day9+1)*24. day == 7 桃子数 == (day8+1)*2
"""# 定义函数,返回对应天数的桃子
def peach(day):if day == 10:return 1# 如果是 1<=day<10的范围就是从后一天开始推导else:return (peach(day + 1) + 1) * 2# 完成测试
print("最初桃子数为:", peach(1))
  1. 求函数值,已知 f(1)= 3; f(n)= 2 * f(n-1)+1;请使用递归的思想编程,求出 f(n)的值?
# @Author :zjc
# @File   :09_recursion_exercise03.py
# Time    :2024/9/2 17:50# 求函数值,已知 f(1)= 3; f(n)= 2 * f(n-1)+1;请使用递归的思想编程,求出 f(n)的值?"""思路分析:1. 已经给出了推推导公式2. 我们将其翻译成对应的代码即可
"""def f(n):if n == 1:return 3else:return 2 * f(n - 1) + 1
print(f(10))

二、递归调用实例-汉诺塔

image-20240902175519289

  • 代码演示
# @Author :zjc
# @File   :010_hannoi_tower.py
# Time    :2024/9/2 17:55def hanoi_tower(num, a, b, c):"""输出num个盘子移动的顺序:param num: 指定盘子数:param a: 表示A柱子:param b: 表示B柱子:param c: 表示C柱子:return:"""# 如果只有一个盘if num == 1:print("第1个盘从:", a, "->", c)else:# 1. 有多个盘,我们认为只有两个,上面所有的盘和最下面的盘# 2. 移动上面所有的盘到B柱子,这个过程会借助到C柱子hanoi_tower(num - 1, a, c, b)# 移动最下面的盘print(f"第{num}个盘从: {a} -> {c}")# 1.把B柱子所有的盘移动到C柱子,这个过程会使用到A柱子hanoi_tower(num - 1, b, a, c)# 测试一把
hanoi_tower(3, "A", "B", "C")

P73 函数作为参数传递 2024/9/3

一、实际需求

  • 请看下面代码
# 看一个实际需求
def f1(num1, num2):max_val = num1 if num1 > num2 else num2return max_valdef f2(num1, num2):max_val = num1 if num1 > num2 else num2return num1 + num, max_val

问题分析:
1.f1和f2都有对两个数求最大值的需求

2.如果有更多的函数也有对两个数求最大的需求,在每个函数都写一份相同代码会冗余,而且,不利用维护

3.解决方案,编写一个函数(该函数可以返回两个数的最大值),

4.将该函数作为参数传给f1,f2就非常棒了->引出知识点:将函数作为参数传递

  • 通过函数改进
# @Author :zjc
# @File   :012_function_arg.py
# Time    :2024/9/3 14:11# 定义一个函数,可以返回两十数的最大值
def get_max_val(num1, num2):max_val = num1 if num1 > num2 else num2return max_valdef f1(fun, num1, num2):"""# 调用fun返回num1和num2的最大值:param fun: 表示接收一个函数:param num1: 传入数:param num2: 传入数:return: 最大值"""return fun(num1, num2)def f2(fun, num1, num2):"""功能:调用fun返回num1和num2的最大值,同时返回两个数的和:param fun::param num1::param num2::return:"""return num1 + num2, fun(num1, num2)# 测试
print(f1(get_max_val, 50, 20))
x, y = f2(get_max_val, 10, 50)
print(f"x = {x},y = {y}")

image-20240903144402199

二、注意事项和细节

注意事项和细节
1、函数作为参数传递,传递的不是数据,而是业务处理逻辑

2、一个函数,可以接收多个函数作为参数传入

# @Author :zjc
# @File   :013_function_arg_02.py
# Time    :2024/9/3 14:36# f3接收多个函数作为参数传入
def f3(my_fun, num1, num2, my_fun2):return my_fun(num1, num2), my_fun2(num1, num2)# 定义一个函数,可以返回两个数的最大值
def get_max_val(num1, num2):max_val = num1 if num1 > num2 else num2return max_val# 定义函数,可以返回两个数的和
def get_sum(num1, num2):return num1 + num2# 演示
x, y = f3(get_max_val, 10, 20, get_sum)
print(f"x = {x},y = {y}")

image-20240903144824659

P74 lambda匿名函数 2024/9/3

一、基本介绍

需求:如果我们有这样一个需求,需要将函数作为参数进行传递,但是这个函数只使用一次,这时,我们可以考虑使用lambda匿名函数。

  • 1、函数的定义

    • def关键字,可以定义带有名称的函数,可以重复使用

    • lambda关键字,可以定义匿名函数(无名称),匿名函数只能使用一次

    • 匿名函数用于临时创建一个函数,只使用一次的场景

  • 2、匿名函数基本语法

    • lambda形参列表:函数体(一行代码)

    • lambda关键字,表示定义匿名函数

    • 形参列表:比如num1, num2表示接收两个参数

    • 函数体:完成的功能,只能写一行,不能写多行代码
  • 应用实例

编写一个函数,可以接收一个匿名函数和两个数,通过匿名函数计算,返回两个数的最大值

# @Author :zjc
# @File   :014_anno_function.py
# Time    :2024/9/3 19:51# 思路分析+代码实现
# 编写一个函数,可以接收一个匿名函数和两个数,通过匿名函数计算,
#返回两个数的最大值def f1(fun, num1, num2):"""功能:调用fun返回num1和num2的最大值:param fun:接收函数(匿名的):param num1::param num2 ::return:"""# 确认接受到的类型print(f"fun类型: {type(fun)}")return fun(num1, num2)# 关键是看如何传入匿名函数调用"""1.lambda a, b: a if a > b else b 就是匿名函数2. 不需要return,运算结果就是返回值
"""
# 无需def定义和起名,更加简洁方便
max_val = f1(lambda a, b: a if a > b else b, 12, 10)
print("最大值 = ",max_val)

P75 变量的作用范围 2024/9/4

一、基本介绍

全局变量: 在整个程序范围内都可以访问,定义在函数外,拥有全局作用域的变量。

局部变量: 只能在其被声明的函数范围内访问,定义在函数内部,拥有局部作用域的变量

  • 案例演示
# @Author :zjc
# @File   :015_globe_part_var.py
# Time    :2024/9/4 16:44# n1就是全局变量
n1 = 100def f1():# n2就是局部变量n2 = 200print(n2)# 可以访问全局变量n1print(n1)f1()
print(n1)# 不能访问局部变量n2
print(n2)

二、注意事项和细节

  1. 未在函数内部重新定义n1,那么默认使用全局变量n1
n1 = 100
def f1():print(n1)f1()
  1. 在函数内部重新定义了n1,那么根据就近原则,使用的就是函数内部重新定义的n1
n1= 100def f1():# n1重新定义了n1 = 200print(n1)f1()
print(n1)
  1. 在函数内部使用global关键字,可以标明指定使用全局变量
n= 100def f1():# global关键字标明使用全局变量n1global n1n1 = 200print(n1)f1()
# n1 的值会发生变化
print(n1)

三、知识点总结

image-20240904174938689

P76 数据容器的概述 2024/9/4

一、问题引出

image-20240904180156361

image-20240904180237529

image-20240904180247676

  • round函数

image-20240904180929215

# @Author :zjc
# @File   :01_hens_questions.py
# Time    :2024/9/4 18:04hen1 = 3
hen2 = 5
hen3 = 1
hen4 = 3.4
hen5 = 2
hen6 = 50
# 计算总的体重
total_weight = hen1 + hen2 + hen3 + hen4 + hen5 + hen6  # 计算平均体重
avg_weight = total_weight / 6
print(f"总体重:{total_weight}平均体重: {round(avg_weight, 2)}") # 保留小数点后两位

image-20240904181029316

  • 问题分析

1.如果不是6只鸡而是600只鸡怎么办?

2.不利于代码的维护,不灵活

3.引出—>列表知识点

二、基本介绍

1、数据容器是一种数据类型,有些地方也简称为容器/collections

2、数据容器可以存放多个数据,每一个数据也被称为一个元素

3、存放的数据/元素可以是任意类型

4、简单的说,数据容器就是I种可以存放多个数据/元素的数据类型

5、简单的示意图

image-20240904200443505

P77 列表基本使用 2024/9/5

参考文档:https://docs.python.org/zh-cn/3.11/library/stdtypes.html#list

image-20240905172648279

一、基本介绍

1、列表可以存放多个不同类型数据,即:列表就是一列数据(多个数据)

2、列表也是一种数据类型

  • 列表的定义
    • 创建一个列表,只要用逗号分隔的不同的数据项使用方括号括起来即可,示例如下:
list1 = [1, 2, 3, 4, 5, 6, 7, 8]
list2 = ["tom", "jack", "mary", "blue"]
  • 说明:为了让大家明白,我画列表内存图说明

image-20240905173057566

比如:你要使用list2列表的第3个值"blue",则通过 list[2]就可以访问到

老韩提示:注意索引是从0开始计算的

  • 代码演示
# @Author :zjc
# @File   :03_list_define.py
# Time    :2024/9/5 19:11# 代码
# 列表的定义"""
老师解读
1.定义了一个列表,名字为list1,值为[100,200,300,400,500]
2.100就是其中的一个数据/元素
"""list1 = [100, 200, 300, 400, 500]
# 输出列表数据
print(list1) # 输出列表的素有数据项和元素项
print(type(list1))
print(list1[0])

image-20240905191331731

二、列表的遍历

  • 什么是列表的遍历:

    简单的说,就是将列表的**每个元素依次取出,**进行处理的操作,就是遍历/迭代

  • list_color = ['red', 'green', 'blue', 'yellow', 'white','black']

  • 使用while循环,对列表进行遍历输出:

    • len()函数介绍:返回对象的长度

image-20240905192327907

# @Author :zjc
# @File   :05_list_while.py
# Time    :2024/9/5 19:21# while 遍历列表
"""
思路分析
1.先定义变量index = 0 表示从第一个元素开始取出
2.决定列表list_color的个数6,这里其实有一个内置函数len(列表),可以返回个数
3.每取出一个就输出 / 或者根据自己的业务处理
"""
list_color = ['red', 'green', 'blue ', 'yellow', 'white ', 'black']# 得到list元素个数
print(len(list_color))# 1. while循环
index = 0
while index < len(list_color):print(f"第{index + 1}个元素", list_color[index])index += 1# 2. for循环
for ele in list_color:print("元素是", ele)

三、解决养鸡场问题

问题:一个养鸡场有6只鸡,它们的体重分别是3kg, 5kg, 1kg, 3.4kg, 2kg, 50kg。请问这六只鸡的总体重是多少?平均体重是多少?请你编写程序计算。

# 使用列表解决养鸡场问题
hens = [3, 5, 1, 3.4, 2, 50]
total_weight = 0.0
# 遍历 hens
for ele in hens:total_weight += eleprint(f"总体重:{total_weight}平均体重: {round(total_weight/len(hens), 2)}")

image-20240905202417570

P78 列表使用细节(1)2024/9/6

一、注意事项和细节

1、如果我们需要一个空列表,可以通过**[]或者list()**方式来定义

官方文档:https://docs.python.org/zh-cn/3.11/library/stdtypes.html#list

image-20240906152338183

# @Author :zjc
# @File   :06_list_detail.py
# Time    :2024/9/6 15:24# 列表使用注意事项和细节
# 1.如果我们需要一个空列表,可以通过,或者list()方式来定义
list1 =[]
list2 = list()
print(list1, type(list1))
print(list2, type(list2))

image-20240906152503228

2、列表的元素可以有多个,而且数据类型没有限制,允许有重复元素,并且是有序的

# 2、列表的数据项可以有多个,而且数据类型没有限制
list3 = [100, "jack", 4.5, "jack"]
print(list3)
# 嵌套列表
list4 = [100, "tom", ["天龙八部", "笑傲江湖", 300]]
print("list4=", list4)

3、列表的索引/下标是从0开始的

4、列表索引必须在指定范围内使用,否则报: IndexError: list index out of range,比如 list1 =[1,2.1,'韩顺平教育']有效下标为0-2

list5 = [1, 2.1, "韩顺平教育"]
# 索引越界
print(list5[3])

5、索引也可以从尾部开始,最后一个元素的索引为-1,往前一位为-2,以此类推

image-20240906153130321

list1 = [1, 2.1, '韩顺平教育']
print(list1[-1])
print(list1[-2])  # 依然不能索引越界
# print(list1[-4])

6、通过列表[索引]=新值对数据进行更新,使用列表.append(值)方法来添加元素,使用del语句来删除列表的元素,注意不能超出有效索引范围

s.append(x)x 添加到序列的末尾 (等同于 s[len(s):len(s)] = [x])
# 通过列表[索引]=新值对数据进行更新,使用列表.append(值)方法来添加元素
list_a = ["天龙八部", "笑傲江湖"]
print("list_a: ", list_a)
list_a[0] = "雪山飞狐"
print("list_a: ", list_a)# 在“笑傲江湖”后面增加元素“倚天屠龙”
list_a.append("倚天屠龙")
print("list_a: ", list_a)# 删除索引为1的元素 ”笑傲江湖“
del list_a[1]
print("list_a->", list_a)

P79 列表使用细节(2)2024/9/6

一、注意事项和细节

7、列表是可变序列(要注意其使用特点),看下面的代码

# 列表的元素是可以修改的,修改后,列表变量指向地址不变,只是数据内容变化
list1 = [1, 2.1, '韩顺平教育']
print(f"list: {list1}地址: {id(list1)},|| {list1[2]} {id(list1[2])}")
# 修改之后元素的地址会发生改变
list1[2] = 'python'# 可以修改
print(f"list: {list1}地址: {id(list1)},|| {list1[2]}  {id(list1[2])}")
# 扩展一下,列表在赋值的特点,示意图说明
list1 = [1, 2.1, '韩顺平教育']
list2 = list1
  • 内存示意图

image-20240906161326948

  • 代码分析1
# 扩展一下,列表在赋值的特点,示意图说明
list1 = [1, 2.1, '韩顺平教育']
list2 = list1
# 修改会影响list1的值
list2[0] = 500
print("list2=", list2)  # 输出?
print("list1=", list1)  # 输出?

image-20240906163045195

  • 示意图

image-20240906162947364

  • 代码分析2
def f1(l):l[0] = 100 # 函数中会改变list10元素[0]的值print("l的id: ", id(l))list10 = [1, 2.1, 200]
print("list10的id: ", id(list10))
f1(list10) # 实际上传递的是地址
print("list10: ", list10)  # 输出?

image-20240906163937524

  • 示意图

image-20240906163919194

相关文章:

  • 爬虫入门 Selenium使用
  • 906. 超级回文数
  • 算法复杂度-空间
  • JAVA红娘婚恋相亲交友系统源码全面解析
  • Java语法-类和对象之抽象类和接口
  • 【软件测试】详解软件测试中的测试级别
  • Stable Diffusion 优秀博客转载
  • Spark 中 任务集 TaskSet 详解
  • 青动CRM V3.2.1
  • 第十四届蓝桥杯真题Python c组F.棋盘(持续更新)
  • Linux 配置与管理 SWAP(虚拟内存)
  • 9月28日
  • 【Fastapi】参数获取,json和query
  • STM32 RTC实时时钟学习总结
  • React Native 在 build iOS 的时候如果出现关于 `metro` 的错误
  • hexo+github搭建个人博客
  • CoolViewPager:即刻刷新,自定义边缘效果颜色,双向自动循环,内置垂直切换效果,想要的都在这里...
  • CSS3 变换
  • Electron入门介绍
  • gitlab-ci配置详解(一)
  • Object.assign方法不能实现深复制
  • quasar-framework cnodejs社区
  • React 快速上手 - 07 前端路由 react-router
  • spring-boot List转Page
  • Three.js 再探 - 写一个跳一跳极简版游戏
  • 看图轻松理解数据结构与算法系列(基于数组的栈)
  • 猫头鹰的深夜翻译:JDK9 NotNullOrElse方法
  • 深度学习在携程攻略社区的应用
  • 网页视频流m3u8/ts视频下载
  • 终端用户监控:真实用户监控还是模拟监控?
  • elasticsearch-head插件安装
  • LIGO、Virgo第三轮探测告捷,同时探测到一对黑洞合并产生的引力波事件 ...
  • ​业务双活的数据切换思路设计(下)
  • #Datawhale AI夏令营第4期#多模态大模型复盘
  • #Spring-boot高级
  • #我与Java虚拟机的故事#连载06:收获颇多的经典之作
  • $NOIp2018$劝退记
  • (C语言)strcpy与strcpy详解,与模拟实现
  • (floyd+补集) poj 3275
  • (附源码)springboot 基于HTML5的个人网页的网站设计与实现 毕业设计 031623
  • (离散数学)逻辑连接词
  • (论文阅读31/100)Stacked hourglass networks for human pose estimation
  • (十六)Flask之蓝图
  • (转) ns2/nam与nam实现相关的文件
  • (转载)hibernate缓存
  • ... 是什么 ?... 有什么用处?
  • .mkp勒索病毒解密方法|勒索病毒解决|勒索病毒恢复|数据库修复
  • .NET Compact Framework 多线程环境下的UI异步刷新
  • .NET Core 网络数据采集 -- 使用AngleSharp做html解析
  • .net websocket 获取http登录的用户_如何解密浏览器的登录密码?获取浏览器内用户信息?...
  • .Net 高效开发之不可错过的实用工具
  • .Net程序猿乐Android发展---(10)框架布局FrameLayout
  • .net快速开发框架源码分享
  • .vimrc php,修改home目录下的.vimrc文件,vim配置php高亮显示
  • @component注解的分类