在深入具体的序列类型之前,让我们先了解Python序列类型的整体框架:
序列类型
├── 可变序列
│ └── 列表(list)
└── 不可变序列
├── range对象
├── 元组(tuple)
└── 字符串(str)
range()是Python中一个非常实用的内置函数,用于生成一个数字序列。它的特点是内存效率高,因为它不会立即生成所有数字,而是在需要时才生成(惰性求值)。
range(stop) # 从0开始,步长为1
range(start, stop) # 指定起始值,步长为1
range(start, stop, step) # 指定起始值、结束值和步长
# 1. 基本用法演示
# 生成0到4的序列(不包含5)
for i in range(5):
print(i) # 输出:0, 1, 2, 3, 4
# 2. 指定起始值和结束值
# 生成2到5的序列(不包含6)
for i in range(2, 6):
print(i) # 输出:2, 3, 4, 5
# 3. 指定步长
# 生成0到10的偶数序列
for i in range(0, 11, 2):
print(i) # 输出:0, 2, 4, 6, 8, 10
# 4. 使用负步长(倒序)
# 从5倒数到1
for i in range(5, 0, -1):
print(i) # 输出:5, 4, 3, 2, 1
# 1. 创建数字列表
numbers = list(range(1, 6)) # [1, 2, 3, 4, 5]
# 2. 实现简单的计数器
def simple_counter(n):
"""一个简单的计数器示例"""
for i in range(n):
print(f'当前计数:{i + 1}')
# 3. 生成自定义数列
def generate_sequence(start, end, step):
"""生成自定义数列并返回列表"""
return list(range(start, end, step))
# 4. 循环索引应用
fruits = ['苹果', '香蕉', '橙子']
for i in range(len(fruits)):
print(f'索引 {i}: {fruits[i]}')
# 5. 九九乘法表生成器
def multiplication_table():
"""使用range生成九九乘法表"""
for i in range(1, 10):
for j in range(1, i + 1):
print(f'{j}×{i}={i*j}\t', end='')
print() # 换行
# 6. 斐波那契数列生成器
def fibonacci(n):
"""生成斐波那契数列的前n项"""
fib = [0, 1]
for i in range(2, n):
fib.append(fib[i-1] + fib[i-2])
return fib
# 演示range()的内存效率
import sys
# 比较range对象和等价列表的内存占用
num_range = range(1000000)
num_list = list(range(1000000))
print(f'range对象占用内存:{sys.getsizeof(num_range)} 字节')
print(f'列表占用内存:{sys.getsizeof(num_list)} 字节')
# range对象的惰性求值演示
def demonstrate_lazy_evaluation():
"""演示range的惰性求值特性"""
large_range = range(10**10) # 创建巨大的range对象,但不会占用大量内存
print(f"第1个元素:{large_range[0]}")
print(f"第1000000个元素:{large_range[999999]}")
print(f"最后一个元素:{large_range[-1]}")
栈是一种后进先出(LIFO - Last In, First Out)的数据结构,就像一摞盘子,最后放上去的盘子最先被拿走。
栈的操作示意图:
压入(push)操作: 弹出(pop)操作:
│ 3 │ │ │
│ 2 │ ====> │ 2 │
│ 1 │ │ 1 │
└───┘ └───┘
class Stack:
def __init__(self):
"""初始化空栈"""
self.items = []
def is_empty(self):
"""检查栈是否为空"""
return len(self.items) == 0
def push(self, item):
"""将元素压入栈顶"""
self.items.append(item)
def pop(self):
"""从栈顶弹出元素"""
if not self.is_empty():
return self.items.pop()
raise IndexError("栈为空")
def peek(self):
"""查看栈顶元素但不移除"""
if not self.is_empty():
return self.items[-1]
raise IndexError("栈为空")
def size(self):
"""返回栈的大小"""
return len(self.items)
# 栈的实际应用示例:括号匹配检查器
def is_balanced_parentheses(expression):
"""检查括号是否匹配
支持的括号类型:(), [], {}
"""
stack = Stack()
brackets = {')': '(', ']': '[', '}': '{'}
for char in expression:
if char in '([{':
stack.push(char)
elif char in ')]}': # 闭括号
if stack.is_empty():
return False
if stack.pop() != brackets[char]:
return False
return stack.is_empty()
# 使用示例
print(is_balanced_parentheses("((()))"))) # True
print(is_balanced_parentheses("(([]))"))) # True
print(is_balanced_parentheses("(()"))) # False
队列是一种先进先出(FIFO - First In, First Out)的数据结构,就像排队买票,先到的人先买票。
队列的操作示意图:
入队(enqueue): 出队(dequeue):
┌───┬───┬───┐ ┌───┬───┐
│ 1 │ 2 │ 3 │ ===> │ 2 │ 3 │
└───┴───┴───┘ └───┴───┘
from collections import deque
class Queue:
def __init__(self):
"""初始化空队列
使用deque而不是list,因为deque的popleft()操作效率更高"""
self.items = deque()
def is_empty(self):
"""检查队列是否为空"""
return len(self.items) == 0
def enqueue(self, item):
"""将元素加入队列尾部"""
self.items.append(item)
def dequeue(self):
"""从队列头部移除元素"""
if not self.is_empty():
return self.items.popleft()
raise IndexError("队列为空")
def front(self):
"""查看队列头部元素但不移除"""
if not self.is_empty():
return self.items[0]
raise IndexError("队列为空")
def size(self):
"""返回队列的大小"""
return len(self.items)
# 队列的实际应用示例:打印任务队列
class PrintTask:
def __init__(self, name, pages):
self.name = name
self.pages = pages
class PrintQueue:
def __init__(self):
self.queue = Queue()
def add_task(self, task):
"""添加打印任务"""
self.queue.enqueue(task)
print(f"添加打印任务:{task.name},{task.pages}页")
def process_tasks(self):
"""处理打印队列"""
while not self.queue.is_empty():
task = self.queue.dequeue()
print(f"正在打印:{task.name},{task.pages}页")
# 模拟打印过程
# 使用示例
printer = PrintQueue()
printer.add_task(PrintTask("报告", 5))
printer.add_task(PrintTask("论文", 12))
printer.add_task(PrintTask("简历", 2))
printer.process_tasks()
元组是Python中的不可变序列类型,一旦创建就不能修改。这种不可变性使得元组在某些场景下比列表更适用。
# 1. 元组的创建方式
# 使用圆括号
empty_tuple = () # 空元组
single_element = (1,) # 单元素元组(注意逗号)
multiple_elements = (1, 2, 3) # 多元素元组
# 不使用圆括号(元组打包)
tuple_packing = 1, 2, 3
# 2. 元组解包
x, y, z = multiple_elements
print(f"x={x}, y={y}, z={z}")
# 3. 元组的基本操作
tuple1 = (1, 2, 3)
print(f"长度:{len(tuple1)}")
print(f"最大值:{max(tuple1)}")
print(f"最小值:{min(tuple1)}")
print(f"元素2的索引:{tuple1.index(2)}")
print(f"元素2的出现次数:{tuple1.count(2)}")
# 4. 元组的切片操作
tuple2 = (1, 2, 3, 4, 5)
print(tuple2[1:4]) # (2, 3, 4)
print(tuple2[::2]) # (1, 3, 5)
# 1. 命名元组
from collections import namedtuple
# 创建一个表示学生的命名元组
Student = namedtuple('Student', ['name', 'age', 'score'])
student1 = Student('小明', 18, 95)
print(f"学生信息:{student1.name}, {student1.age}岁, 分数{student1.score}")
# 2. 元组作为字典键
# 使用元组存储坐标点
coordinate_values = {(0, 0): '原点',
(1, 0): 'x轴上的点',
(0, 1): 'y轴上的点'}
# 3. 返回多个值
def calculate_stats(numbers):
"""计算一组数的统计信息"""
count = len(numbers)
total = sum(numbers)
average = total / count
minimum = min(numbers)
maximum = max(numbers)
return count, total, average, minimum, maximum
# 使用元组解包接收多个返回值
data = [1, 2, 3, 4, 5]
count, total, avg, min_val, max_val = calculate_stats(data)
print(f"数据统计:\n数量:{count}\n总和:{total}\n平均值:{avg}\n最小值:{min_val}\n最大值:{max_val}")
# 4. 元组用作数据记录
class WeatherRecord:
def __init__(self):
self.daily_records = [] # 存储每日天气记录
def add_record(self, date, temperature, humidity, pressure):
"""添加天气记录
使用元组存储每日天气数据,保证数据不被意外修改"""
record = (date, temperature, humidity, pressure)
self.daily_records.append(record)
def get_record(self, index):
"""获取指定日期的天气记录"""
if 0 <= index < len(self.daily_records):
return self.daily_records[index]
return None
# 使用示例
weather = WeatherRecord()
weather.add_record('2024-01-01', 25.5, 60, 1013)
weather.add_record('2024-01-02', 26.0, 65, 1012)
# 5. 元组解包的高级技巧
# 5.1 使用*运算符解包
first, *rest = (1, 2, 3, 4, 5)
print(f"第一个元素:{first}, 剩余元素:{rest}") # 输出:第一个元素:1, 剩余元素:[2, 3, 4, 5]
*begin, last = (1, 2, 3, 4, 5)
print(f"前面的元素:{begin}, 最后一个元素:{last}") # 输出:前面的元素:[1, 2, 3, 4], 最后一个元素:5
# 5.2 同时解包多个元组
points = [(1, 2), (3, 4), (5, 6)]
for x, y in points:
print(f"x坐标:{x}, y坐标:{y}")
# 6. 元组作为不可变容器的优势
# 6.1 作为字典的键
user_locations = {}
# 元组可以作为字典的键,因为它是不可变的
user_locations[(39.9, 116.4)] = '北京'
user_locations[(31.2, 121.5)] = '上海'
user_locations[(22.5, 114.1)] = '深圳'
# 6.2 在集合中使用
unique_coordinates = {(0, 0), (1, 1), (2, 2)}
# 6.3 数据安全性示例
class Configuration:
def __init__(self):
# 使用元组存储配置项,防止被修改
self._settings = (
('debug_mode', False),
('max_connections', 100),
('timeout', 30)
)
def get_setting(self, name):
"""获取配置项的值"""
for key, value in self._settings:
if key == name:
return value
return None
# 7. 命名元组的高级用法
from collections import namedtuple
# 7.1 创建具有默认值的命名元组
Person = namedtuple('Person', ['name', 'age', 'city'], defaults=['未知'])
person1 = Person('张三', 25) # city将使用默认值'未知'
# 7.2 命名元组的方法
Point = namedtuple('Point', ['x', 'y'])
p1 = Point(3, 4)
# 转换为字典
point_dict = p1._asdict()
print(f"转换为字典:{point_dict}") # 输出:{'x': 3, 'y': 4}
# 创建新实例并替换字段
p2 = p1._replace(x=5)
print(f"原始点:{p1}, 新的点:{p2}") # p1的x=3, p2的x=5
# 7.3 命名元组继承
class AdvancedPoint(Point):
def calculate_distance(self):
"""计算到原点的距离"""
return (self.x ** 2 + self.y ** 2) ** 0.5
ap = AdvancedPoint(3, 4)
print(f"到原点的距离:{ap.calculate_distance()}") # 输出:5.0
# 8. 元组在数据处理中的应用
# 8.1 数据分组和聚合
def group_by_category(data):
"""将数据按类别分组"""
categories = {}
for item, category, value in data:
if category not in categories:
categories[category] = []
categories[category].append((item, value))
return categories
# 示例数据
sales_data = [
('产品A', '电子', 1000),
('产品B', '服装', 500),
('产品C', '电子', 1500),
('产品D', '服装', 800)
]
grouped_data = group_by_category(sales_data)
for category, items in grouped_data.items():
print(f"\n类别:{category}")
for item, value in items:
print(f"{item}: {value}")
# 8.2 数据验证
def validate_record(record):
"""验证数据记录的完整性"""
required_fields = ('id', 'name', 'price', 'quantity')
# 检查字段数量
if len(record) != len(required_fields):
return False
# 检查数据类型
try:
id_, name, price, quantity = record
return (
isinstance(id_, int) and
isinstance(name, str) and
isinstance(price, (int, float)) and
isinstance(quantity, int)
)
except:
return False
# 测试数据验证
valid_record = (1, '商品A', 99.9, 10)
print(f"数据验证结果:{validate_record(valid_record)}") # True
invalid_record = (1, '商品B', '无效价格', 5)
print(f"数据验证结果:{validate_record(invalid_record)}") # False
特性 | 列表(List) | 元组(Tuple) |
---|---|---|
可变性 | 可变 | 不可变 |
语法 | [1, 2, 3] | (1, 2, 3) |
内存效率 | 较低 | 较高 |
执行效率 | 较低 | 较高 |
应用场景 | 需要频繁修改的数据集合 | 固定数据、多值返回、数据安全 |
# 1. 可变性对比
my_list = [1, 2, 3]
my_tuple = (1, 2, 3)
# 列表可以修改
my_list[0] = 10 # 正常执行
my_list.append(4) # 正常执行
# 元组不可修改
try:
my_tuple[0] = 10 # 抛出 TypeError
except TypeError as e:
print("元组是不可变的:", e)
# 2. 内存占用对比
import sys
list_size = sys.getsizeof([1, 2, 3])
tuple_size = sys.getsizeof((1, 2, 3))
print(f"列表内存占用:{list_size} 字节")
print(f"元组内存占用:{tuple_size} 字节")
# 3. 性能对比
import timeit
# 创建速度对比
list_creation = timeit.timeit(stmt="[1, 2, 3, 4, 5]", number=1000000)
tuple_creation = timeit.timeit(stmt="(1, 2, 3, 4, 5)", number=1000000)
print(f"列表创建时间:{list_creation}秒")
print(f"元组创建时间:{tuple_creation}秒")
# 4. 应用场景示例
# 4.1 列表适用场景:数据需要频繁修改
def shopping_cart():
cart = [] # 使用列表存储购物车商品
cart.append("苹果")
cart.append("香蕉")
cart.remove("苹果") # 删除商品
return cart
# 4.2 元组适用场景:固定数据结构
def get_coordinates():
return (39.9, 116.4) # 返回经纬度坐标
# 4.3 元组作为字典键
point_data = {(0, 0): "原点", (1, 0): "x轴单位点"}
# 4.4 命名元组用于结构化数据
from collections import namedtuple
Point = namedtuple('Point', ['x', 'y'])
point = Point(3, 4)
print(f"x坐标:{point.x}, y坐标:{point.y}")
list(range(size))
# 列表性能优化示例
# 1. 不好的方式
def bad_list_creation():
numbers = []
for i in range(1000):
numbers.append(i)
return numbers
# 2. 优化的方式
def good_list_creation():
return list(range(1000)) # 更高效
# 3. 使用列表推导式
def list_comprehension():
return [x * 2 for x in range(1000)] # 高效且易读
# 元组性能优化示例
# 1. 直接创建元组
coordinates = (1, 2, 3) # 好
# 2. 避免不必要的转换
bad_tuple = tuple([1, 2, 3]) # 不推荐
good_tuple = (1, 2, 3) # 推荐
# 3. 使用命名元组增强代码可读性和维护性
Person = namedtuple('Person', ['name', 'age', 'city'])
person = Person('张三', 25, '北京')
print(f"{person.name}来自{person.city}")