从0开始转入Ai应用层,从python学起第九天
一、深浅拷贝
核心概念:Python变量存储的是对象的引用(内存地址),而非数据本身。深浅拷贝的区别,本质就是“新对象的引用指向哪里”。
用人话理解:
- 浅拷贝 = 藕断丝连(只复制外层,内部嵌套的可变对象还是共享的)
- 深拷贝 = 完全独立(全部复制,原对象怎么改都不影响新对象)
核心区别:是否复制嵌套的可变对象(如列表里的列表)。
1. 三种操作对比(核心示例)
import copy
names = [1, 2, [3, 4]]
# 直接赋值:共享同一内存,改一个全变
names1 = names
# 深拷贝:完全独立,互不影响
names2 = copy.deepcopy(names)
names2[0] = 5
print(names2) # [5, 2, [3, 4]]
print(names) # [1, 2, [3, 4]] 不变
# 浅拷贝:只复制外层,内层列表共享
names3 = copy.copy(names)
names3[0] = 6
print(names3) # [6, 2, [3, 4]]
print(names) # [1, 2, [3, 4]] 外层不受影响
# 修改嵌套元素,浅拷贝跟着变,深拷贝不受影响
names[2][0] = 77
print(names) # [1, 2, [77, 4]]
print(names3) # [6, 2, [77, 4]] 浅拷贝跟着变了
print(names2) # [5, 2, [3, 4]] 深拷贝不受影响
2. 深浅拷贝核心区别表
| 操作 | 创建新外层容器 | 嵌套可变对象共享 | 改嵌套元素影响原数据 |
|---|---|---|---|
直接赋值 = |
否 | 完全共享 | 影响 |
| 浅拷贝 | 是 | 共享 | 影响 |
| 深拷贝 | 是 | 不共享 | 不影响 |
3. 常用实现方式
| 数据类型 | 浅拷贝方式 | 深拷贝方式 |
|---|---|---|
| 列表 | list.copy() / lst[:] / copy.copy() |
copy.deepcopy() |
| 字典 | dict.copy() / copy.copy() |
copy.deepcopy() |
| 集合 | set.copy() / copy.copy() |
copy.deepcopy() |
4. 实用注意点
- 不可变对象无需拷贝:字符串、数字、内部无可变元素的元组,拷贝后仍指向同一内存,修改直接创建新对象,无需区分深浅拷贝。
- 无嵌套用浅拷贝:如果数据没有嵌套可变对象,浅拷贝效率更高(深拷贝递归复制,耗时耗内存)。
- 循环引用慎用深拷贝:如
a=[1]; b=[a]; a.append(b)会导致深拷贝变慢。
深浅拷贝总结:
- 浅拷贝:只复制外层,内部嵌套可变对象仍共享。
- 深拷贝:完全独立,修改任何层级互不影响。
- 选择原则:无嵌套用浅拷贝,有嵌套且需独立用深拷贝,仅需引用用直接赋值。
二、函数基础定义与调用
函数:组织好的、可重复使用的代码段,能提高代码复用率和可读性。用 def 关键字定义,通过函数名调用。
1. 基础语法
def 函数名(参数1, 参数2, ...):
"""函数文档字符串(可选,说明功能)"""
# 函数体(要执行的代码)
执行逻辑
return 返回值 # 可选,无return则返回None
# 调用函数
结果 = 函数名(值1, 值2, ...)
2. 三种基本形式
# 无参数,无返回值
def names():
print("你好呀,我是函数,我被调用了")
names() # 可重复调用
# 有参数,无返回值
def name(a):
print(f"你好,我是{a}")
name("张三")
# 有参数,有返回值
def jk(a, b):
return a + b
result = jk(1, 2)
print(result)
3. 函数的参数(核心重点)
参数是函数的“输入”,Python支持多种参数类型:
2.1 位置参数(必选参数)
最基础的参数,调用时必须按顺序传递,数量要匹配。
def names(name, age):
print(f"这是:{name}, 这是{age}")
names("张三", 18) # 必须按顺序
2.2 默认参数
定义时给参数指定默认值,调用时可省略该参数。
def names(name, age=18): # age是默认参数
print(f"这是:{name}, 这是{age}")
names("张三") # 使用默认值age=18
names("王五", 20) # 覆盖默认值
注意:默认参数必须放在位置参数后面,默认值最好用不可变对象。
2.3 关键字参数
调用时通过 参数名=值 传参,顺序可任意。
def names(name, age):
print(f"这是:{name}, 这是{age}")
names(name="张三", age=18)
names(age=20, name="王五") # 顺序可以乱
2.4 可变长度参数(*args 和**kwargs)
处理“不确定数量的参数”,高频用法:
*args:接收任意数量的位置参数,打包成元组。
def names(*args):
print(args)
names("张三", 18) # ('张三', 18)
names("张三", 18, "上海") # ('张三', 18, '上海')
**kwargs:接收任意数量的关键字参数,打包成字典。
def names(**kwargs):
print(kwargs)
names(name="张三", age=18) # {'name': '张三', 'age': 18}
names(name="张三", age=18, city="上海") # {'name': '张三', 'age': 18, 'city': '上海'}
解包参数(结合拆包):
def names(name, age):
print(f"这是:{name}, 这是{age}")
names(*["张三", 18]) # 用*解包列表
names(*("张三", 18)) # 用*解包元组
三、函数的操作
1. 函数的返回值
- 用
return返回结果,执行到return函数立即结束。 - 无
return或return后无值,默认返回None。 - 可返回多个值,本质是返回元组(自动打包),接收时可拆包。
# 返回单个值
def get_unit(num):
if num >= 100:
return '百'
elif num >= 10:
return '十'
else:
return '个'
print(get_unit(10)) # '十'
# 返回多个值
def get_unit(num):
if num >= 100:
return '百', '看这里'
elif num >= 10:
return '十', '看这里'
else:
return '个', '看这里'
result, msg = get_unit(10) # 拆包接收
print(result, msg) # 十 看这里
2. 函数的作用域
- 局部变量:函数内部定义的变量,仅在函数内生效,外部无法访问。
- 全局变量:函数外部定义的变量,全局生效,函数内可读取(但修改需加
global关键字)。
# 局部变量
def names():
name = "张三"
print(name)
names()
# print(name) # 报错,访问不到局部变量
# 全局变量
name = "张三"
def names():
print(name) # 可以读取全局变量
names()
print(name)
3. 匿名函数(lambda)
用 lambda 定义极简函数,适用于一行代码的简单逻辑。
语法:lambda 参数: 表达式
# 普通写法
def add(a, b):
return a + b
print(add(1, 2))
# 匿名函数
add = lambda a, b: a + b
print(add(1, 2))
4. 函数的复用(嵌套与递归)
嵌套函数:函数内部定义另一个函数,内层函数可访问外层函数的变量。
def outer():
x = 10
def inner():
print(x + 5) # 访问外层变量
inner()
outer() # 输出: 15
递归函数:函数调用自身,必须有终止条件,否则无限递归。
# 计算阶乘:n! = n * (n-1)!,终止条件: 0! = 1
def factorial(n):
if n == 1:
return 1
return n * factorial(n - 1)
print(factorial(5)) # 输出: 120 (5*4*3*2*1)
今日核心总结
-
深浅拷贝:
- 直接赋值:共享同一内存,改一个全变。
- 浅拷贝:只复制外层,嵌套可变对象仍共享。
- 深拷贝:完全独立,互不影响。
- 选择原则:无嵌套用浅拷贝,有嵌套且需独立用深拷贝。
-
函数核心:用
def定义,通过函数名调用,return返回结果(无则返回None)。 -
参数类型(重点):
- 位置参数:必须按顺序传递。
- 默认参数:有默认值,可省略,必须放在位置参数后面。
- 关键字参数:通过
参数名=值传参,顺序可任意。 *args:接收任意数量位置参数,打包成元组。**kwargs:接收任意数量关键字参数,打包成字典。
-
关键概念:
- 返回值:可返回多个值(本质是元组),接收时可拆包。
- 作用域:局部变量函数内有效,全局变量全局有效。
lambda:一行代码的匿名函数,适合简单逻辑。- 递归:函数调用自身,必须有终止条件。
注:已经使用DeepSeek进行整理精简核心内容,些许不理解的配合个人笔记进行理解。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)