大模型学习-python基础Day10
一.python高级语法
1.深拷贝和浅拷贝
直接赋值:对象的引用,不产生拷贝
浅拷贝:拷贝父对象,不会拷贝对象的内部的子对象。拷贝后只有第一层是独立的
深拷贝:完全拷贝了父对象及其子对象。拷贝后所有层都是独立的
如何浅拷贝
列表可通过完整切片实现浅拷贝:
original = [1, [2, 3], 4]
copied = original[:] # 全切片拷贝
标准库的copy模块提供通用copy()函数:
import copy
original = [[1, 2], [3, 4]]
shallow_copied = copy.copy(original)
使用list()或dict()构造函数:
original_dict = {'a': 1, 'b': [2, 3]}
copied_dict = dict(original_dict) # 字典浅拷贝
如何深拷贝
使用copy模块的deepcopy函数
import copy
list2 = copy.deepcopy(list1)
拷贝的特殊情况
非容器类型(如数字、字符串、和其他原子类型的对象)无法拷贝
import copy
var1 = 1
print(id(var1),var1) #1400000001 1
var2 = copy.copy(var1)
print(id(var2),var2) #1400000001 1
var3 = copy.deepcopy(var1)
print(id(var3),var3) #1400000001 1
元组变量如果只包含原子类型
import copy
tuple1 = (1,2,3)
print(id(tuple1),tuple1) #13000001 (1,2,3)
tuple2 = copy.deepcopy(tuple1)
print(id(tuple2),tuple2) #13000001 (1,2,3)
2.迭代器
迭代器是一种设计模式,用于顺序访问集合对象的元素,而不需要暴露其底层表示。它提供了一种统一的方式来遍历不同的数据结构。
迭代器的核心功能
- 遍历集合:迭代器允许按顺序访问集合中的每个元素。
- 解耦遍历逻辑:将遍历逻辑从集合中分离出来,使集合和遍历逻辑可以独立变化。
- 支持多种遍历方式:同一集合可以支持多种遍历方式(如正向、反向、按条件过滤等)
字符串、元组或列表都可以创建迭代器
可迭代对象
大多数容器对象可以使用for语句,for底层就是迭代器
可直接作用于for循环的数据类型有以下几种:
容器,如list、tuple、dict、set、str等
generator,包括生成器和带yield的generator function
这些可以直接作用于for循环的对象成为可迭代对象:Iterable
for item in [1, 2, 3]:
print(item)
for item in (1, 2, 3):
print(item)
with open("file.txt") as f:
for line in f:
print(line.strip())
生成器generator
gen = (x * 2 for x in range(3))
for num in gen:
print(num) # 0, 2, 4
判断是非是可迭代的对象 Iterable:能直接使用for遍历,低层实现__iter__,当调用iter()时候会调用
from collections.abc import Iterable
print(isinstance(要判断的对象, Iterable))
判断对象是不是迭代器 Iterator:低层实现__iter__,当调用iter()时候会调用;低层实现__next__,当调用next()时候会调用;
from collections.abc import Iterator
print(isinstance(要判断的对象, Iterator))
使用迭代器
迭代器有两个基本方法:iter()和next()
Python中的迭代器协议基于两个核心方法,它们共同实现了迭代功能:
iter()
- 返回迭代器对象本身,通常直接返回
self - 该方法使得迭代器对象可以被用于
for循环等迭代场景 - 必须实现该方法才能使对象成为可迭代对象
next()
- 返回迭代中的下一个值
- 当没有更多元素时,需要抛出
StopIteration异常 - 每次调用都会推进迭代器的状态
迭代器的工作机制
使用for循环时,Python会自动调用iter()方法来获取迭代器对象,然后重复调用next()方法直到捕获StopIteration异常。这使得迭代器可以逐个返回元素而不需要一次性加载所有数据到内存
#我们可以使用iter()获取一个可迭代对象的迭代器,并使用next()遍历迭代器
list = [1,2,3]
it = iter(list) #创建迭代器对象
print(next(it)) #输出迭代器的下一个元素,1
print(next(it)) #输出迭代器的下一个元素,2
print(next(it)) #输出迭代器的下一个元素,3
print(next(it)) #stopIteration
#也可以使用for来遍历迭代器
list = [1,2,3]
it = iter(list) #创建迭代器对象
for i in it:
print(i)
创建迭代器
定义__iter__()方法用于返回一个带有__next__()方法的对象。如果类定义了__next__(),那么__iter__()可以简单返回self。
class ReverseIterator:
def __init__(self, sequence):
self.sequence = sequence
self.index = len(sequence)
def __iter__(self):
return self
def __next__(self):
if self.index > 0:
self.index -= 1
return self.sequence[self.index]
raise StopIteration
# 使用示例
my_list = [1, 2, 3, 4, 5]
for item in ReverseIterator(my_list):
print(item)
3.生成器
生成器是用于创建迭代器的简单而强大的工具。他的写法类似于标准的函数,当他要返回数据时会使用yield语句。当生成器函数中使用yield语句时,函数的执行会暂停,并将yield后的表达式作为当前迭代的值返回
- 可迭代:支持
for循环或next()调用。
创建生成器
通过推导式创建生成器
generator = (expression for item in iterable if condition)
gen = (i for i in range(100))
for i in gen:
print(i)
使用函数创建生成器
在函数中使用 yield 关键字代替 return,函数调用时返回一个生成器对象:
def count_up_to(n):
count = 1
while count <= n:
yield count
count += 1
generator = count_up_to(5)
for num in generator:
print(num)
生成斐波那契数列的生成器
def fibonacci_gen(max_num):
a, b = 0, 1
while a < max_num:
#生成器通过yield进行值的返回
yield a
a, b = b, a + b
# 使用生成器表达式实现类似功能
fib_gen = (fib for fib in fibonacci_gen(100)) # 生成小于100的斐波那契数
生成器函数的返回值获取方法
生成器函数通过yield语句产生值,而非return。要获取其返回值,需遍历生成器或手动调用next()。
通过next()获取包含value和done属性的对象,最后一次调用可拿到return值:
const gen = genFunc();
console.log(gen.next().value); // 1
console.log(gen.next().value); // 2
console.log(gen.next().value); // 3
send()
向生成器发送值
生成器的 send 方法语法如下:
generator.send(value)
value 是发送给生成器的值,该值会成为当前 yield 表达式的结果。
恢复执行并向生成器函数发送一个值,这个值作为当前yield表达式的结果。send()方法会返回生成器所产生的下一个值,或者如果生成器没有产生下一个值就退出则会引发stopIteration
def generator_function():
value_received = yield "initial value"
yield f"Received: {value_received}"
gen = generator_function()
print(next(gen)) # 输出: "initial value"
print(gen.send("Hello")) # 输出: "Received: Hello"
-
初始化生成器
调用生成器函数不会立即执行代码,而是返回一个生成器对象。需要使用next()或send(None)启动生成器,使其运行到第一个yield语句。 -
发送值到生成器
通过send(value)方法可以向生成器传递值,该值会被赋值给yield左侧的变量。 -
继续执行生成器
send()方法会恢复生成器的执行,直到遇到下一个yield或生成器结束。
send(none)
如果send 方法启动生成器,首次调用时必须传入 None,因为生成器刚开始执行时没有 yield 表达式来接收值。
例如:
gen = my_generator()
print(gen.send(None)) # 等同于 next(gen)
print(gen.send(10))
4.命名空间
一般有三种命名空间,在不同时刻创建,且拥有不同的生命周期。命名空间(Namespace)是编程中用于组织和管理代码标识符(如变量、函数、类等)的一种机制。它通过将相关标识符分组到特定名称下,避免命名冲突,尤其在大型项目或多模块协作中尤为重要。
内置名称
内置名称的命名空间在python解释器启动时创建,永远不会被删除
一个模块的全局名称
模块的全局命名空间在读取模块定义时创建。通常,模块的命名空间会持续到解释器退出。从脚本文件读取或者交互式读取的,由解释器顶层调用执行的语句,是__main__模块调用的一部分,也拥有自己的全局命名空间。内置名称实际也在模块里,即builtins。
一个函数调用中的局部名称
函数的局部命名空间在函数被调用时被创建,并在函数返回或抛出为在函数内被处理的异常时被删除(实际上,用遗忘来描述实际发生情况会更好一些)。当然,每次递归调用都有自己的局部空间。
闭包命名空间
嵌套函数中,外层函数的命名空间对内部函数可见,但不属于全局命名空间。
命名空间的查找顺序(LEGB 规则)
Python 查找变量时遵循 LEGB 规则:
- L(Local):先在当前函数或方法内部查找。
- E(Enclosing):如果当前函数是嵌套函数,则查找外层函数的命名空间。
- G(Global):在模块级别查找。
- B(Built-in):最后查找内置命名空间。
5.作用域
什么是作用域
一个命名空间的作用域是python代码中的一段文本区域,从这个区域可直接访问该
6.闭包
什么是闭包
闭包(Closure)是 Python 中一种特殊的函数对象,能够访问并记住其所在词法作用域(即定义时的作用域)中的变量,即使函数在定义的作用域之外被调用。闭包的核心特点是函数嵌套以及对外部变量的引用。
闭包的形成条件
- 函数嵌套:一个函数内部定义了另一个函数。
- 内部函数引用外部变量:内部函数使用了外部函数的局部变量或参数。
- 外部函数返回内部函数:外部函数将内部函数作为返回值。
闭包的使用
def outer_func():
outer_var = "外部变量"
def inner_func():
print(outer_var) # 内部函数访问外部变量
return inner_func
closure = outer_func()
closure() # 输出: "外部变量"
查看闭包中的值
所有函数对象都有一个__closure__属性,如果它是一个闭包函数,则该属性返回单元格对象的元组,每个单元格对象都对应着闭包所引用的外部函数作用域中的一个变量。对于普通函数,__closure__属性的值通常为None。
单元格对象(cell 对象)存储闭包引用的变量值,通过 cell_contents 属性访问:
def linear(a,b):
def inner(x):
return a*x + b
return inner
y1 = linear(1,2)
objects = y1.__closure__
print(objects)
print(objects[0].cell_contents) #1
print(objects[0].cell_contents) #2
7.装饰器
什么是装饰器
装饰器允许在不修改原有函数代码的基础上,动态地增加或修改函数的功能。装饰器本质上是一个接受函数作为输入并返回一个新的包装过后的函数的对象。
使用装饰器
语法
def decorator(func)
def inner(参数)
#添加功能
func(参数)
#添加功能
return inner
decorator是一个装饰器函数,他接受一个函数func作为参数,并返回一个内部函数inner。在inner函数内部,我们可以执行一些额外的操作,然后调用原始函数func,并返回其结果。
闭包实现装饰器
from math import sqrt
def func(x):
return sqrt(x)
def decorator(f)
def inner(x)
x = abs(x)
return f(x)
return inner
inn = decorator(func)
print(inn(-4))
装饰器语法糖(@decorator使用装饰器)
当我们使用@decorator前缀在func定义前,python会自动将func作为参数传递给decorator,然后将返回的inner函数替换掉原来的func。
def my_decorator(func):
def wrapper():
print("Before function call")
func()
print("After function call")
return wrapper
@my_decorator
def say_hello():
print("Hello!")
say_hello()
示例:
from math import sqrt
def decorator(f)
def inner(x)
x = abs(x)
return f(x)
return inner
@decorator
def func(x):
return sqrt(x)
print(func(-4))
多层装饰器
离函数最近的装饰器先执行,再执行函数远的装饰器
执行顺序:装饰器从下往上调用,但实际执行时外层装饰器的逻辑先触发
from math import sqrt
def get_abs(f)
def inner(x)
x = abs(x)
return f(x)
return inner
def get_integer(f):
def inner(x):
x = int(x)
return f(x)
return inner
@get_abs
@get_integer
def func(x):
return sqrt(x)
"""
abs_inner = get_abs(func)
get_integer(abs_inner)
print(abs_inner("-4"))
"""
print(func("-4)")
带参数的装饰器
from math import sqrt
def times(n):
def get_abs(f)
def inner(x)
x = abs(x)
for i in range(n)
x = f(x)
return x
return inner
return get_abs
@times(2)
def func(x):
return sqrt(x)
print(func(-4))
类装饰器
类装饰器是包含__call__()方法的类,它接受函数作为参数,并且返回新的函数。
在 Python 中,__call__() 方法允许类的实例像函数一样被调用。定义该方法后,直接对实例使用括号运算符即可触发。
class CallableClass:
def __call__(self, *args, **kwargs):
print("实例被调用,参数:", args, kwargs)
obj = CallableClass()
obj("参数1", key="参数2")
实例被调用,参数: ('参数1',) {'key': '参数2'}
示例:
from math import sqrt
class DecoratorClass:
def __init__(self,f)
self.f = f
def __call__(self,x)
x = abs(x)
return self.f(x)
@DecoratorClass
def fnc(x)
return sqrt(x)
printf(func(-1))
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)