大纲概览
- 闭包与装饰器
-
- 闭包:一个内部函数,它包含了对外部函数作用域(非全局作用域)中变量的引用。
- 装饰器:一种在不修改原函数代码的情况下,给函数增加额外功能的技术。
- 生成器
-
- 生成器是迭代器的一种,但它只在迭代到该元素时才计算该元素的值,而不是一次性生成所有元素。
- 使用yield关键字创建生成器。
- 序列化
-
- 序列化:将数据结构或对象状态转换为可以存储或传输的形式的过程。
- 反序列化:是序列化的逆过程,即将序列化后的形式转换回数据结构或对象状态。
闭包与装饰器
- 闭包示例
-
- f1()函数是闭包函数,它调用了func()并将func()的返回值加1后返回。
- f2()函数用于创建闭包,接受一个函数作为参数并返回一个新的函数。
- 装饰器
-
- 装饰器使用@符号将装饰器函数与被装饰函数联系起来。
- 示例中,f2是一个装饰器函数,它接受一个函数作为参数并返回一个新函数f1,f1会调用原函数func并添加额外功能。
- 装饰器改进
-
- 使用@符号使得装饰器更加简洁和易于使用。
生成器
- 生成器基础
-
- 使用yield关键字定义生成器函数。
- 调用生成器函数时,它不会立即执行函数体,而是返回一个生成器对象。
- 使用next()函数或for循环来迭代生成器对象,每次迭代执行到yield语句时,会暂停并返回yield后面的值。
- 示例
def func(): print("111") yield 222 gener = func() # 获取生成器对象
ret = gener.__next__() # 执行生成器,获取第一个yield的值
print(ret) # 输出: 222
文档提及
- JSON
-
- json.dumps(obj):将Python对象转换为JSON字符串。
- json.loads(s):将JSON字符串转换为Python对象。
- json.dump(obj, file):将Python对象写入文件,并转换为JSON格式。
- json.load(file):从文件中读取JSON数据,并转换为Python对象。
- Pickle
-
- 用于Python特有的类型(如自定义类)和Python数据类型间的转换。
- 与JSON相比,pickle支持更多Python数据类型,但生成的序列化数据不可读,且不是跨语言的。
函数进阶
1. 间接调用函数
- 直接调用函数:直接使用函数名加参数列表调用函数。
- 间接调用函数:
-
- 将函数名赋值给变量,再通过变量名加形参列表调用。
- 一个函数作为另一个函数的参数。
- 函数名作为其他数据类型的元素(如列表、字典等)。
2. 匿名函数
- 匿名函数:没有函数名称的临时微函数,使用lambda表达式声明。
- 语法格式:lambda [arg1, arg2, ..., argn]: expression
- 应用场景:当函数只有一个返回值且只有一句代码时,使用lambda简化。
- 注意:lambda表达式只能包含一个表达式,且必须有返回值,但可以调用其他函数。
3. 生成器
- 生成器与函数的区别:在函数中使用yield代替return,函数就变成了生成器函数。
- 执行生成器函数时,不会立即执行函数体,而是返回一个生成器对象。
- 使用next()方法或迭代访问生成器中的元素,每次调用next()或迭代时,生成器会执行到下一个yield语句并返回其值。
- 生成器是惰性求值的,即按需生成数据,不会一次性加载所有数据到内存中,节省内存。
4. send()与next()方法
- send()和next()方法都可以使生成器执行到下一个yield语句。
- send()可以向上一个yield的位置传递值(但不能给最后一个yield发送值),next()则没有此功能。
- 第一次执行生成器代码时,不能使用send()方法,应使用next()启动生成器。
示例代码
# 示例1:匿名函数
sum_func = lambda x, y: x + y
print(sum_func(3, 5)) # 输出:8 # 示例2:生成器
def fibonacci(): a, b = 0, 1 while True: yield a a, b = b, a + b fib = fibonacci()
print(next(fib)) # 输出:0
print(next(fib)) # 输出:1 # 示例3:send()与next()
def eat(): print("我吃什么?") a = yield "馒头" print("a=", a) b = yield "大饼" print("b=", b) c = yield "韭菜盒子" print("c=", c) yield "GAME OVER" gen = eat()
print(next(gen)) # 输出:"我吃什么?" 和 "馒头"
print(gen.send("胡辣汤")) # 输出:"a=胡辣汤" 和 "大饼"
print(gen.send("狗粮")) # 输出:"b=狗粮" 和 "韭菜盒子"
1. 生成器与迭代器
- 生成器:通过yield关键字定义的函数,称为生成器函数。执行生成器函数时,不会立即执行函数体中的代码,而是返回一个生成器对象。这个对象是一个迭代器,可以通过next()方法或for循环逐个获取其中的值。
- 迭代器:迭代器是一种可以记住遍历的位置的对象。迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。
2. 生成器的使用
- 使用next()方法:调用生成器对象的__next__()方法(通常简写为next())可以获取生成器中的下一个值。如果生成器已经遍历完所有的值,再次调用next()会抛出StopIteration异常。
- 使用for循环:由于生成器是一个迭代器,因此可以直接使用for循环遍历生成器中的值,无需手动调用next()方法。
3. send()方法
- send()方法是生成器特有的一个方法,它的功能与next()类似,都可以让生成器执行到下一个yield语句。但send()方法可以向生成器发送一个值,这个值会被上一个yield表达式接收。
- 注意:在第一次执行生成器代码时,不能使用send()方法,应使用next()或for循环来启动生成器。
4. 生成器表达式与列表推导式
- 生成器表达式:使用圆括号()包围的推导式,它返回的是一个生成器对象,而不是列表。生成器表达式在需要时才计算生成值,因此更加节省内存。
- 列表推导式:使用方括号[]包围的推导式,它返回的是一个列表。列表推导式会一次性生成所有的值,因此会占用更多的内存。
5. 示例代码
- 生成器函数示例:
def eat(): print("我吃什什么啊") a = yield "馒头" print("a=", a) b = yield "大饼" print("b=", b) c = yield "韭菜盒子" print("c=", c) yield "GAME OVER" gen = eat()
print(next(gen)) # 输出: 馒头
print(gen.send("胡辣汤")) # 输出: 大饼
print(gen.send("狗粮")) # 输出: 韭菜盒子
- 生成器表达式示例:
# 生成一个从1到5的平方的生成器
squares = (x**2 for x in range(1, 6))
for square in squares: print(square) # 输出: 1, 4, 9, 16, 25
6. 总结
- 生成器提供了一种高效的方式来处理大量数据,它们只会在需要时才生成值,从而节省了大量的内存空间。
- 迭代器和生成器是Python中处理序列数据的重要工具,它们提供了一种灵活的方式来遍历和操作数据。
- send()方法为生成器提供了与上一个yield位置交互的能力,使得生成器在处理数据时更加灵活。
- 生成器表达式和列表推导式在语法上非常相似,但它们在内存使用和处理方式上有着显著的区别。