第6天-高级特性
哪吒 2023/6/15
# 第6天-Python高级特性
恭喜你!经过前5天的学习,你已经掌握了Python的基础语法。今天我们来学习Python的高级特性,这些特性让Python变得更加强大和优雅!
# 为什么要学习高级特性?
想象一下:
- 🚗 普通开车:只会开车,但不知道GPS、自动泊车等高级功能
- 🏎️ 高级驾驶:熟练使用各种辅助功能,驾驶更轻松高效
Python的高级特性就像汽车的高级功能,让你的编程更加简洁、高效、优雅!
# 一、列表推导式(List Comprehension)
# 1.1 什么是列表推导式?
列表推导式是Python创建列表的一种简洁而强大的方法,可以用一行代码完成复杂的列表生成。
生活类比:就像工厂流水线,输入原材料,经过加工,输出成品列表。
# 1.2 基本语法
# 基本语法:[表达式 for 变量 in 可迭代对象]
new_list = [expression for item in iterable]
# 带条件的语法:[表达式 for 变量 in 可迭代对象 if 条件]
new_list = [expression for item in iterable if condition]
# 1.3 从传统方法到列表推导式
# 传统方法:生成1到10的平方
squares_traditional = []
for i in range(1, 11):
squares_traditional.append(i ** 2)
print(squares_traditional)
# 输出:[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
# 列表推导式:一行搞定!
squares_comprehension = [i ** 2 for i in range(1, 11)]
print(squares_comprehension)
# 输出:[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
# 效果相同,但列表推导式更简洁!
# 1.4 带条件的列表推导式
# 筛选偶数并求平方
numbers = range(1, 11)
even_squares = [x ** 2 for x in numbers if x % 2 == 0]
print(even_squares) # 输出:[4, 16, 36, 64, 100]
# 处理字符串列表
words = ['hello', 'world', 'python', 'programming']
# 筛选长度大于5的单词并转为大写
long_words = [word.upper() for word in words if len(word) > 5]
print(long_words) # 输出:['PYTHON', 'PROGRAMMING']
# 处理嵌套数据
students = [('Alice', 85), ('Bob', 92), ('Charlie', 78), ('Diana', 96)]
# 筛选分数大于80的学生姓名
high_scorers = [name for name, score in students if score > 80]
print(high_scorers) # 输出:['Alice', 'Bob', 'Diana']
# 1.5 嵌套列表推导式
# 创建二维列表(矩阵)
matrix = [[i * j for j in range(1, 4)] for i in range(1, 4)]
print(matrix)
# 输出:[[1, 2, 3], [2, 4, 6], [3, 6, 9]]
# 展平二维列表
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flattened = [num for row in matrix for num in row]
print(flattened) # 输出:[1, 2, 3, 4, 5, 6, 7, 8, 9]
小白提示:嵌套列表推导式从左到右读:先外层循环,再内层循环。
# 二、字典推导式(Dict Comprehension)
# 2.1 基本语法
# 基本语法:{键表达式: 值表达式 for 变量 in 可迭代对象}
new_dict = {key_expr: value_expr for item in iterable}
# 带条件:{键表达式: 值表达式 for 变量 in 可迭代对象 if 条件}
new_dict = {key_expr: value_expr for item in iterable if condition}
# 2.2 实际应用示例
# 创建数字到平方的映射
square_dict = {x: x**2 for x in range(1, 6)}
print(square_dict) # 输出:{1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
# 字符串长度映射
words = ['apple', 'banana', 'cherry', 'date']
word_lengths = {word: len(word) for word in words}
print(word_lengths)
# 输出:{'apple': 5, 'banana': 6, 'cherry': 6, 'date': 4}
# 筛选并转换字典
original_dict = {'a': 1, 'b': 2, 'c': 3, 'd': 4}
# 只保留值为偶数的项,并将值翻倍
even_doubled = {k: v*2 for k, v in original_dict.items() if v % 2 == 0}
print(even_doubled) # 输出:{'b': 4, 'd': 8}
# 交换键值对
original = {'name': 'Alice', 'age': '25', 'city': 'Beijing'}
swapped = {v: k for k, v in original.items()}
print(swapped) # 输出:{'Alice': 'name', '25': 'age', 'Beijing': 'city'}
# 三、集合推导式(Set Comprehension)
# 3.1 基本用法
# 基本语法:{表达式 for 变量 in 可迭代对象}
new_set = {expression for item in iterable}
# 创建平方数集合
squares_set = {x**2 for x in range(1, 6)}
print(squares_set) # 输出:{1, 4, 9, 16, 25}
# 去重功能
numbers = [1, 2, 2, 3, 3, 4, 5, 5]
unique_squares = {x**2 for x in numbers}
print(unique_squares) # 输出:{1, 4, 9, 16, 25}
# 字符串处理
text = "Hello World"
unique_chars = {char.lower() for char in text if char.isalpha()}
print(unique_chars) # 输出:{'h', 'e', 'l', 'o', 'w', 'r', 'd'}
# 四、生成器(Generator)
# 4.1 什么是生成器?
生成器是一种特殊的迭代器,它按需生成数据,而不是一次性创建所有数据。
生活类比:
- 列表:像一次性买一箱苹果,占用很多冰箱空间
- 生成器:像果园,需要时才摘一个苹果,节省空间
# 4.2 生成器表达式
# 生成器表达式:用圆括号代替方括号
squares_gen = (x**2 for x in range(1, 6))
print(type(squares_gen)) # 输出:<class 'generator'>
# 逐个获取值
print(next(squares_gen)) # 输出:1
print(next(squares_gen)) # 输出:4
print(next(squares_gen)) # 输出:9
# 或者用for循环遍历
squares_gen = (x**2 for x in range(1, 6))
for square in squares_gen:
print(square)
# 输出:1 4 9 16 25
# 4.3 yield关键字
def fibonacci_generator(n):
"""生成斐波那契数列的前n项"""
a, b = 0, 1
count = 0
while count < n:
yield a # 返回当前值,但函数不结束
a, b = b, a + b
count += 1
# 使用生成器
fib_gen = fibonacci_generator(10)
for num in fib_gen:
print(num, end=' ')
# 输出:0 1 1 2 3 5 8 13 21 34
print() # 换行
# 生成器的内存优势
def large_range_list(n):
"""传统方法:创建大列表"""
return [i for i in range(n)]
def large_range_generator(n):
"""生成器方法:按需生成"""
for i in range(n):
yield i
# 对比内存使用(这里只是演示概念)
import sys
# 小数据量时差别不大
small_list = large_range_list(100)
small_gen = large_range_generator(100)
print(f"列表大小:{sys.getsizeof(small_list)} 字节")
print(f"生成器大小:{sys.getsizeof(small_gen)} 字节")
# 4.4 生成器的实际应用
def read_large_file(filename):
"""逐行读取大文件,节省内存"""
with open(filename, 'r', encoding='utf-8') as file:
for line in file:
yield line.strip()
def process_data_stream():
"""模拟数据流处理"""
data = range(1000000) # 模拟大量数据
for item in data:
if item % 2 == 0: # 只处理偶数
yield item * 2
# 使用生成器处理大量数据
processed_data = process_data_stream()
# 只取前10个结果
for i, value in enumerate(processed_data):
if i >= 10:
break
print(value, end=' ')
# 输出:0 4 8 12 16 20 24 28 32 36
# 五、迭代器(Iterator)
# 5.1 理解迭代器
# 可迭代对象 vs 迭代器
my_list = [1, 2, 3, 4, 5] # 可迭代对象
my_iterator = iter(my_list) # 迭代器
print(type(my_list)) # <class 'list'>
print(type(my_iterator)) # <class 'list_iterator'>
# 使用迭代器
print(next(my_iterator)) # 1
print(next(my_iterator)) # 2
print(next(my_iterator)) # 3
# 迭代器只能向前,不能后退
# print(next(my_iterator)) # 4
# print(next(my_iterator)) # 5
# print(next(my_iterator)) # StopIteration 异常
# 5.2 自定义迭代器
class CountDown:
"""倒计时迭代器"""
def __init__(self, start):
self.start = start
def __iter__(self):
return self
def __next__(self):
if self.start <= 0:
raise StopIteration
self.start -= 1
return self.start + 1
# 使用自定义迭代器
countdown = CountDown(5)
for num in countdown:
print(f"倒计时:{num}")
# 输出:
# 倒计时:5
# 倒计时:4
# 倒计时:3
# 倒计时:2
# 倒计时:1
# 六、装饰器进阶
# 6.1 带参数的装饰器
def repeat(times):
"""重复执行装饰器"""
def decorator(func):
def wrapper(*args, **kwargs):
for i in range(times):
result = func(*args, **kwargs)
return result
return wrapper
return decorator
@repeat(3)
def greet(name):
print(f"Hello, {name}!")
greet("Alice")
# 输出:
# Hello, Alice!
# Hello, Alice!
# Hello, Alice!
# 6.2 类装饰器
class Timer:
"""计时装饰器类"""
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
import time
start = time.time()
result = self.func(*args, **kwargs)
end = time.time()
print(f"{self.func.__name__} 执行时间:{end - start:.4f}秒")
return result
@Timer
def slow_function():
import time
time.sleep(1)
return "完成"
result = slow_function()
print(result)
# 6.3 多个装饰器组合
def bold(func):
def wrapper(*args, **kwargs):
result = func(*args, **kwargs)
return f"<b>{result}</b>"
return wrapper
def italic(func):
def wrapper(*args, **kwargs):
result = func(*args, **kwargs)
return f"<i>{result}</i>"
return wrapper
@bold
@italic
def say_hello(name):
return f"Hello, {name}!"
print(say_hello("World"))
# 输出:<b><i>Hello, World!</i></b>
# 七、高阶函数
# 7.1 map()函数
# map(function, iterable) - 将函数应用到每个元素
numbers = [1, 2, 3, 4, 5]
# 使用普通函数
def square(x):
return x ** 2
squared = list(map(square, numbers))
print(squared) # [1, 4, 9, 16, 25]
# 使用lambda函数
squared_lambda = list(map(lambda x: x ** 2, numbers))
print(squared_lambda) # [1, 4, 9, 16, 25]
# 处理字符串
words = ['hello', 'world', 'python']
uppercase = list(map(str.upper, words))
print(uppercase) # ['HELLO', 'WORLD', 'PYTHON']
# 多个可迭代对象
nums1 = [1, 2, 3]
nums2 = [4, 5, 6]
sums = list(map(lambda x, y: x + y, nums1, nums2))
print(sums) # [5, 7, 9]
# 7.2 filter()函数
# filter(function, iterable) - 过滤元素
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# 筛选偶数
even_numbers = list(filter(lambda x: x % 2 == 0, numbers))
print(even_numbers) # [2, 4, 6, 8, 10]
# 筛选大于5的数
greater_than_5 = list(filter(lambda x: x > 5, numbers))
print(greater_than_5) # [6, 7, 8, 9, 10]
# 筛选非空字符串
words = ['hello', '', 'world', '', 'python']
non_empty = list(filter(None, words)) # None会过滤掉假值
print(non_empty) # ['hello', 'world', 'python']
# 自定义过滤函数
def is_long_word(word):
return len(word) > 5
words = ['cat', 'elephant', 'dog', 'hippopotamus']
long_words = list(filter(is_long_word, words))
print(long_words) # ['elephant', 'hippopotamus']
# 7.3 reduce()函数
from functools import reduce
# reduce(function, iterable[, initializer]) - 累积操作
numbers = [1, 2, 3, 4, 5]
# 计算总和
total = reduce(lambda x, y: x + y, numbers)
print(total) # 15
# 计算乘积
product = reduce(lambda x, y: x * y, numbers)
print(product) # 120
# 找最大值
max_value = reduce(lambda x, y: x if x > y else y, numbers)
print(max_value) # 5
# 字符串连接
words = ['Hello', ' ', 'World', '!']
sentence = reduce(lambda x, y: x + y, words)
print(sentence) # "Hello World!"
# 带初始值
numbers = [1, 2, 3, 4, 5]
total_with_init = reduce(lambda x, y: x + y, numbers, 100)
print(total_with_init) # 115 (100 + 15)
# 7.4 zip()函数
# zip(*iterables) - 打包多个可迭代对象
names = ['Alice', 'Bob', 'Charlie']
ages = [25, 30, 35]
cities = ['Beijing', 'Shanghai', 'Guangzhou']
# 基本用法
combined = list(zip(names, ages))
print(combined) # [('Alice', 25), ('Bob', 30), ('Charlie', 35)]
# 三个列表组合
full_info = list(zip(names, ages, cities))
print(full_info)
# [('Alice', 25, 'Beijing'), ('Bob', 30, 'Shanghai'), ('Charlie', 35, 'Guangzhou')]
# 解包zip结果
for name, age, city in zip(names, ages, cities):
print(f"{name}, {age}岁, 来自{city}")
# zip的逆操作:解包
combined = [('Alice', 25), ('Bob', 30), ('Charlie', 35)]
names_unpacked, ages_unpacked = zip(*combined)
print(names_unpacked) # ('Alice', 'Bob', 'Charlie')
print(ages_unpacked) # (25, 30, 35)
# 不同长度的列表(以最短为准)
short_list = [1, 2]
long_list = [10, 20, 30, 40]
result = list(zip(short_list, long_list))
print(result) # [(1, 10), (2, 20)]
# 八、上下文管理器(with语句)
# 8.1 文件操作的最佳实践
# 传统方法(不推荐)
file = open('example.txt', 'w')
file.write('Hello, World!')
file.close() # 容易忘记关闭
# 使用with语句(推荐)
with open('example.txt', 'w') as file:
file.write('Hello, World!')
# 自动关闭文件,即使出现异常也会关闭
# 读取文件
with open('example.txt', 'r') as file:
content = file.read()
print(content) # Hello, World!
# 8.2 自定义上下文管理器
class Timer:
"""计时上下文管理器"""
def __enter__(self):
import time
self.start = time.time()
print("开始计时...")
return self
def __exit__(self, exc_type, exc_val, exc_tb):
import time
self.end = time.time()
print(f"执行时间:{self.end - self.start:.4f}秒")
# 使用自定义上下文管理器
with Timer():
import time
time.sleep(1)
print("执行一些操作...")
# 输出:
# 开始计时...
# 执行一些操作...
# 执行时间:1.0012秒
# 8.3 使用contextlib简化
from contextlib import contextmanager
@contextmanager
def timer_context():
import time
start = time.time()
print("开始计时...")
try:
yield
finally:
end = time.time()
print(f"执行时间:{end - start:.4f}秒")
# 使用
with timer_context():
import time
time.sleep(0.5)
print("执行操作...")
# 九、类型注解(Type Hints)
# 9.1 基本类型注解
# 变量类型注解
name: str = "Alice"
age: int = 25
height: float = 1.68
is_student: bool = True
# 函数类型注解
def greet(name: str, age: int) -> str:
return f"Hello, {name}! You are {age} years old."
def calculate_area(length: float, width: float) -> float:
"""计算矩形面积"""
return length * width
# 使用
result = greet("Bob", 30)
area = calculate_area(5.0, 3.0)
print(result)
print(f"面积:{area}")
# 9.2 复杂类型注解
from typing import List, Dict, Tuple, Optional, Union
# 列表类型
def process_numbers(numbers: List[int]) -> List[int]:
return [n * 2 for n in numbers]
# 字典类型
def get_student_info() -> Dict[str, Union[str, int]]:
return {"name": "Alice", "age": 20, "grade": "A"}
# 元组类型
def get_coordinates() -> Tuple[float, float]:
return (39.9042, 116.4074)
# 可选类型
def find_user(user_id: int) -> Optional[str]:
users = {1: "Alice", 2: "Bob"}
return users.get(user_id) # 可能返回None
# 联合类型
def process_id(user_id: Union[int, str]) -> str:
return str(user_id)
# 使用示例
numbers = [1, 2, 3, 4, 5]
doubled = process_numbers(numbers)
print(doubled) # [2, 4, 6, 8, 10]
student = get_student_info()
print(student) # {'name': 'Alice', 'age': 20, 'grade': 'A'}
coords = get_coordinates()
print(coords) # (39.9042, 116.4074)
user = find_user(1)
print(user) # Alice
user_id = process_id(123)
print(user_id) # "123"
# 十、实战练习
# 10.1 数据处理综合练习
# 学生成绩数据处理
students_data = [
{'name': 'Alice', 'scores': [85, 92, 78, 96]},
{'name': 'Bob', 'scores': [76, 88, 82, 79]},
{'name': 'Charlie', 'scores': [95, 87, 91, 93]},
{'name': 'Diana', 'scores': [68, 74, 82, 79]}
]
# 使用列表推导式计算每个学生的平均分
average_scores = [
{
'name': student['name'],
'average': sum(student['scores']) / len(student['scores'])
}
for student in students_data
]
print("平均分:")
for student in average_scores:
print(f"{student['name']}: {student['average']:.2f}")
# 使用filter筛选优秀学生(平均分>85)
excellent_students = list(filter(
lambda s: s['average'] > 85,
average_scores
))
print("\n优秀学生:")
for student in excellent_students:
print(f"{student['name']}: {student['average']:.2f}")
# 使用map转换数据格式
student_names = list(map(lambda s: s['name'].upper(), excellent_students))
print(f"\n优秀学生姓名(大写):{student_names}")
# 10.2 文件处理生成器
def process_log_file(filename: str):
"""处理日志文件的生成器"""
try:
with open(filename, 'r', encoding='utf-8') as file:
for line_num, line in enumerate(file, 1):
line = line.strip()
if line and not line.startswith('#'): # 跳过空行和注释
yield line_num, line
except FileNotFoundError:
print(f"文件 {filename} 不存在")
# 创建示例日志文件
with open('sample.log', 'w', encoding='utf-8') as f:
f.write("""# 这是注释
INFO: 应用启动
WARNING: 内存使用率较高
ERROR: 数据库连接失败
# 另一个注释
INFO: 重新连接成功
""")
# 使用生成器处理文件
print("处理日志文件:")
for line_num, content in process_log_file('sample.log'):
print(f"第{line_num}行: {content}")
# 10.3 装饰器实战
from functools import wraps
import time
def cache(func):
"""简单的缓存装饰器"""
cache_dict = {}
@wraps(func)
def wrapper(*args, **kwargs):
# 创建缓存键
key = str(args) + str(sorted(kwargs.items()))
if key in cache_dict:
print(f"缓存命中: {func.__name__}")
return cache_dict[key]
print(f"计算中: {func.__name__}")
result = func(*args, **kwargs)
cache_dict[key] = result
return result
return wrapper
def timing(func):
"""计时装饰器"""
@wraps(func)
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(f"{func.__name__} 执行时间: {end - start:.4f}秒")
return result
return wrapper
@cache
@timing
def fibonacci(n: int) -> int:
"""计算斐波那契数列(递归版本)"""
if n <= 1:
return n
return fibonacci(n-1) + fibonacci(n-2)
# 测试缓存效果
print("第一次计算:")
result1 = fibonacci(10)
print(f"fibonacci(10) = {result1}")
print("\n第二次计算(应该使用缓存):")
result2 = fibonacci(10)
print(f"fibonacci(10) = {result2}")
# 十一、总结
# 11.1 高级特性对比表
特性 | 优点 | 使用场景 | 注意事项 |
---|---|---|---|
列表推导式 | 简洁、高效 | 数据转换、过滤 | 不要过度复杂化 |
生成器 | 节省内存 | 大数据处理、流式处理 | 只能遍历一次 |
装饰器 | 代码复用、功能增强 | 日志、缓存、权限验证 | 理解执行顺序 |
高阶函数 | 函数式编程 | 数据处理、函数组合 | 可读性考虑 |
类型注解 | 代码可读性、IDE支持 | 大型项目、团队协作 | 运行时不强制 |
# 11.2 最佳实践建议
- 适度使用:不要为了炫技而使用高级特性
- 可读性优先:代码要让其他人能够理解
- 性能考虑:在需要时才优化性能
- 团队规范:与团队保持一致的编码风格
# 11.3 下一步学习方向
掌握了这些高级特性后,你可以继续学习:
- 模块和包:代码组织和管理
- 面向对象编程:类的高级特性
- 异常处理:错误处理和调试
- 文件和IO操作:数据持久化
- 网络编程:Web开发基础
恭喜你!掌握了这些高级特性,你的Python编程能力已经上了一个台阶!🚀
练习建议:
- 重写之前的代码,使用列表推导式简化
- 尝试创建自己的生成器函数
- 编写实用的装饰器
- 练习使用高阶函数处理数据
- 为自己的函数添加类型注解