目录
[1 位运算](#1 位运算)
[1.1 基本位运算符](#1.1 基本位运算符)
[1.2 位运算实用技巧](#1.2 位运算实用技巧)
[1.3 掩码操作](#1.3 掩码操作)
[1.4 位运算在算法中的应用](#1.4 位运算在算法中的应用)
[1.5 位运算性能优化示例](#1.5 位运算性能优化示例)
[1.6 注意事项](#1.6 注意事项)
[2 python list 用法](#2 python list 用法)
[2.1 创建列表](#2.1 创建列表)
[2.2 访问列表元素](#2.2 访问列表元素)
[2.3 修改列表](#2.3 修改列表)
[2.4 删除元素](#2.4 删除元素)
[2.5 列表方法](#2.5 列表方法)
[2.6 列表推导式](#2.6 列表推导式)
[2.7 列表操作技巧](#2.7 列表操作技巧)
[2.8 多维列表(嵌套列表)](#2.8 多维列表(嵌套列表))
[2.9 性能注意事项](#2.9 性能注意事项)
[2.10 实用示例](#2.10 实用示例)
概述
Python 提供了多种位运算操作符,这些操作符直接对整数的二进制位进行操作。列表(List)是 Python 中最常用的数据结构之一,它是一种有序、可变、可重复的集合。列表是 Python 中最灵活、最强大的数据结构之一。掌握列表的各种用法对于编写高效、简洁的 Python 代码至关重要。
1 位运算
位运算在Python中是非常强大的工具,尤其在以下场景中特别有用:
处理二进制数据
优化性能关键代码
实现某些算法(如位掩码、状态压缩)
与硬件交互或处理底层数据
掌握位运算可以帮助你编写更高效、更简洁的代码,特别是在处理大量数据或性能敏感的应用中。
1.1 基本位运算符
python
# 基本示例
a = 10 # 二进制: 1010
b = 4 # 二进制: 0100
print(f"a = {a} (二进制: {bin(a)})")
print(f"b = {b} (二进制: {bin(b)})")
# 1. 按位与 (&) - 两个位都为1时,结果才为1
print(f"a & b = {a & b} (二进制: {bin(a & b)})") # 1010 & 0100 = 0000 (0)
# 2. 按位或 (|) - 两个位有一个为1时,结果就为1
print(f"a | b = {a | b} (二进制: {bin(a | b)})") # 1010 | 0100 = 1110 (14)
# 3. 按位异或 (^) - 两个位不同时,结果为1
print(f"a ^ b = {a ^ b} (二进制: {bin(a ^ b)})") # 1010 ^ 0100 = 1110 (14)
# 4. 按位取反 (~) - 每个位取反
print(f"~a = {~a} (二进制: {bin(~a & 0b1111)})") # ~1010 = 0101 (5) 但需要注意Python的补码表示
# 5. 左移 (<<) - 所有位向左移动,右侧补0
print(f"a << 2 = {a << 2} (二进制: {bin(a << 2)})") # 1010 << 2 = 101000 (40)
# 6. 右移 (>>) - 所有位向右移动,左侧补0(对正整数)
print(f"a >> 1 = {a >> 1} (二进制: {bin(a >> 1)})") # 1010 >> 1 = 0101 (5)
1.2 位运算实用技巧
python
# 1. 检查奇偶性
def is_even(n):
return (n & 1) == 0
print(f"5是偶数吗?{is_even(5)}") # False
print(f"8是偶数吗?{is_even(8)}") # True
# 2. 检查是否是2的幂
def is_power_of_two(n):
return n > 0 and (n & (n - 1)) == 0
print(f"8是2的幂吗?{is_power_of_two(8)}") # True
print(f"10是2的幂吗?{is_power_of_two(10)}") # False
# 3. 交换两个数的值(不使用临时变量)
x, y = 5, 9
print(f"交换前: x={x}, y={y}")
x ^= y
y ^= x
x ^= y
print(f"交换后: x={x}, y={y}")
# 4. 获取最低位的1
def get_lowest_set_bit(n):
return n & -n
print(f"12的最低位的1: {get_lowest_set_bit(12)} (二进制: {bin(get_lowest_set_bit(12))})")
# 5. 移除最低位的1
def clear_lowest_set_bit(n):
return n & (n - 1)
print(f"移除12的最低位的1: {clear_lowest_set_bit(12)} (二进制: {bin(clear_lowest_set_bit(12))})")
# 6. 统计二进制中1的个数
def count_set_bits(n):
count = 0
while n:
n &= (n - 1) # 每次移除最低位的1
count += 1
return count
print(f"12的二进制中1的个数: {count_set_bits(12)}")
# Python内置方法
print(f"Python内置方法统计12的二进制中1的个数: {bin(12).count('1')}")
1.3 掩码操作
python
# 使用掩码操作特定位
# 1. 设置某一位为1
def set_bit(n, pos):
return n | (1 << pos)
num = 0b1010 # 10
print(f"将第1位设置为1: {bin(set_bit(num, 1))}") # 0b1010 -> 0b1010 | 0b0010 = 0b1010 (不变)
print(f"将第2位设置为1: {bin(set_bit(num, 2))}") # 0b1010 -> 0b1010 | 0b0100 = 0b1110 (14)
# 2. 清除某一位(设置为0)
def clear_bit(n, pos):
return n & ~(1 << pos)
print(f"清除第1位: {bin(clear_bit(num, 1))}") # 0b1010 & ~0b0010 = 0b1010 & 0b1101 = 0b1000 (8)
# 3. 切换某一位(0变1,1变0)
def toggle_bit(n, pos):
return n ^ (1 << pos)
print(f"切换第1位: {bin(toggle_bit(num, 1))}") # 0b1010 ^ 0b0010 = 0b1000 (8)
print(f"切换第2位: {bin(toggle_bit(num, 2))}") # 0b1010 ^ 0b0100 = 0b1110 (14)
# 4. 检查某一位是否为1
def check_bit(n, pos):
return (n & (1 << pos)) != 0
print(f"第1位是1吗?{check_bit(num, 1)}") # True (0b1010 & 0b0010 = 0b0010 ≠ 0)
print(f"第2位是1吗?{check_bit(num, 2)}") # False (0b1010 & 0b0100 = 0)
# 5. 提取多个位
def extract_bits(n, start, length):
mask = (1 << length) - 1
return (n >> start) & mask
num = 0b11011010 # 218
print(f"提取第2-5位: {bin(extract_bits(num, 2, 4))}") # 0b1101
1.4 位运算在算法中的应用
python
# 1. 只出现一次的数字(其他数字都出现两次)
def single_number(nums):
result = 0
for num in nums:
result ^= num
return result
print(f"只出现一次的数字: {single_number([4, 1, 2, 1, 2])}") # 4
# 2. 子集生成(使用位掩码)
def generate_subsets(nums):
n = len(nums)
subsets = []
for mask in range(1 << n): # 2^n 种可能
subset = []
for i in range(n):
if mask & (1 << i): # 检查第i位是否为1
subset.append(nums[i])
subsets.append(subset)
return subsets
nums = [1, 2, 3]
subsets = generate_subsets(nums)
print(f"{nums}的所有子集:")
for subset in subsets:
print(subset)
# 3. 计算两个整数的和(不使用+和-)
def add_without_operator(a, b):
while b != 0:
carry = a & b # 计算进位
a = a ^ b # 计算无进位和
b = carry << 1 # 进位左移
return a
print(f"5 + 7 = {add_without_operator(5, 7)}")
1.5 位运算性能优化示例
python
import time
# 比较乘除2的运算速度
def test_performance():
n = 10000000
start = time.time()
# 使用算术运算
result1 = 0
for i in range(n):
result1 = i * 2
mid = time.time()
# 使用位运算
result2 = 0
for i in range(n):
result2 = i << 1
end = time.time()
print(f"算术运算时间: {mid - start:.6f}秒")
print(f"位运算时间: {end - mid:.6f}秒")
print(f"时间差: {(mid - start) - (end - mid):.6f}秒")
# test_performance()
1.6 注意事项
python
# 1. Python中整数的位数是动态的,没有固定位数限制
large_num = 1 << 1000
print(f"1 << 1000 的位数: {large_num.bit_length()}")
# 2. 处理负数时需要注意
negative_num = -10
print(f"-10 的二进制表示: {bin(negative_num)}")
print(f"-10 >> 1 = {-10 >> 1} (二进制: {bin(-10 >> 1)})")
# 3. 与0xFF等掩码配合使用可以限制位数
value = 300
print(f"300的16位表示: {value & 0xFFFF} (二进制: {bin(value & 0xFFFF)})")
2 python list 用法
2.1 创建列表
python
# 1. 空列表
empty_list = []
empty_list2 = list()
# 2. 包含元素的列表
numbers = [1, 2, 3, 4, 5]
fruits = ['apple', 'banana', 'cherry']
mixed = [1, 'hello', 3.14, True]
# 3. 使用 list() 构造函数
list_from_string = list('hello') # ['h', 'e', 'l', 'l', 'o']
list_from_range = list(range(5)) # [0, 1, 2, 3, 4]
list_from_tuple = list((1, 2, 3)) # [1, 2, 3]
# 4. 列表推导式
squares = [x**2 for x in range(10)] # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
even_numbers = [x for x in range(20) if x % 2 == 0] # [0, 2, 4, ..., 18]
print("创建的各种列表:")
print(f"numbers: {numbers}")
print(f"fruits: {fruits}")
print(f"mixed: {mixed}")
print(f"list_from_string: {list_from_string}")
print(f"squares: {squares}")
2.2 访问列表元素
python
# 创建示例列表
fruits = ['apple', 'banana', 'cherry', 'date', 'elderberry']
# 1. 索引访问(从0开始)
print(fruits[0]) # apple
print(fruits[2]) # cherry
# 2. 负数索引(从末尾开始)
print(fruits[-1]) # elderberry
print(fruits[-2]) # date
# 3. 切片访问 [start:end:step]
print(fruits[1:3]) # ['banana', 'cherry'] # 包含1,不包含3
print(fruits[:3]) # ['apple', 'banana', 'cherry'] # 从头开始
print(fruits[2:]) # ['cherry', 'date', 'elderberry'] # 到末尾
print(fruits[::2]) # ['apple', 'cherry', 'elderberry'] # 每隔一个
print(fruits[::-1]) # 反转列表
# 4. 长度
print(len(fruits)) # 5
# 5. 检查元素是否存在
print('banana' in fruits) # True
print('grape' in fruits) # False
# 6. 遍历列表
print("遍历列表:")
for fruit in fruits:
print(fruit)
print("带索引遍历:")
for index, fruit in enumerate(fruits):
print(f"{index}: {fruit}")
print("反向遍历:")
for fruit in reversed(fruits):
print(fruit)
2.3 修改列表
python
fruits = ['apple', 'banana', 'cherry']
# 1. 修改单个元素
fruits[1] = 'blueberry'
print(f"修改后: {fruits}") # ['apple', 'blueberry', 'cherry']
# 2. 修改多个元素(切片赋值)
fruits[1:3] = ['blackberry', 'cantaloupe']
print(f"切片修改后: {fruits}") # ['apple', 'blackberry', 'cantaloupe']
# 3. 添加元素
fruits.append('date') # 末尾添加
print(f"append 后: {fruits}") # ['apple', 'blackberry', 'cantaloupe', 'date']
fruits.insert(1, 'apricot') # 在指定位置插入
print(f"insert 后: {fruits}") # ['apple', 'apricot', 'blackberry', 'cantaloupe', 'date']
# 4. 扩展列表
more_fruits = ['elderberry', 'fig']
fruits.extend(more_fruits) # 添加多个元素
print(f"extend 后: {fruits}")
# 也可以使用 + 或 +=
fruits += ['grape', 'honeydew']
print(f"+= 后: {fruits}")
2.4 删除元素
python
fruits = ['apple', 'banana', 'cherry', 'date', 'elderberry', 'fig', 'grape']
# 1. del 语句
del fruits[1] # 删除索引为1的元素
print(f"del 后: {fruits}") # ['apple', 'cherry', 'date', 'elderberry', 'fig', 'grape']
del fruits[2:4] # 删除切片
print(f"del 切片后: {fruits}") # ['apple', 'cherry', 'fig', 'grape']
# 2. pop() - 删除并返回指定位置的元素
popped = fruits.pop() # 默认删除最后一个
print(f"pop() 后: {fruits}, 弹出的元素: {popped}")
popped = fruits.pop(1) # 删除指定位置
print(f"pop(1) 后: {fruits}, 弹出的元素: {popped}")
# 3. remove() - 删除第一个匹配的元素
fruits.remove('apple')
print(f"remove('apple') 后: {fruits}")
# 4. clear() - 清空列表
fruits.clear()
print(f"clear() 后: {fruits}") # []
2.5 列表方法
python
numbers = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]
# 1. count() - 统计元素出现次数
print(f"5出现的次数: {numbers.count(5)}") # 3
# 2. index() - 查找元素首次出现的索引
print(f"第一个5的索引: {numbers.index(5)}") # 4
print(f"从索引6开始找5: {numbers.index(5, 6)}") # 9
# 3. sort() - 原地排序
numbers.sort()
print(f"升序排序: {numbers}")
numbers.sort(reverse=True)
print(f"降序排序: {numbers}")
# 4. sorted() - 返回新排序列表(不改变原列表)
unsorted = [3, 1, 4, 1, 5]
sorted_list = sorted(unsorted)
print(f"原列表: {unsorted}")
print(f"排序后新列表: {sorted_list}")
# 5. reverse() - 原地反转
numbers.reverse()
print(f"反转后: {numbers}")
# 6. copy() - 浅拷贝
original = [1, 2, [3, 4]]
copied = original.copy()
original[2][0] = 99
print(f"浅拷贝: 原列表 {original}, 拷贝列表 {copied}") # 注意嵌套列表被共享
# 7. 深拷贝
import copy
deep_copied = copy.deepcopy(original)
original[2][1] = 100
print(f"深拷贝: 原列表 {original}, 深拷贝列表 {deep_copied}")
2.6 列表推导式
python
# 1. 基本推导式
squares = [x**2 for x in range(10)]
print(f"平方数: {squares}")
# 2. 带条件的推导式
even_squares = [x**2 for x in range(10) if x % 2 == 0]
print(f"偶数的平方: {even_squares}")
# 3. 嵌套循环推导式
pairs = [(x, y) for x in range(3) for y in range(3)]
print(f"坐标对: {pairs}")
# 4. 嵌套列表推导式(矩阵转置)
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
transposed = [[row[i] for row in matrix] for i in range(3)]
print(f"矩阵转置: {transposed}")
# 5. 条件表达式(类似三元表达式)
labels = ['偶数' if x % 2 == 0 else '奇数' for x in range(10)]
print(f"奇偶标签: {labels}")
# 6. 嵌套推导式展平列表
nested = [[1, 2, 3], [4, 5], [6, 7, 8, 9]]
flattened = [item for sublist in nested for item in sublist]
print(f"展平嵌套列表: {flattened}")
2.7 列表操作技巧
python
# 1. 列表拼接
list1 = [1, 2, 3]
list2 = [4, 5, 6]
combined = list1 + list2
print(f"列表拼接: {combined}")
# 2. 重复列表
repeated = [1, 2] * 3
print(f"列表重复: {repeated}")
# 3. 解包列表
first, *middle, last = [1, 2, 3, 4, 5]
print(f"first: {first}, middle: {middle}, last: {last}")
# 4. 列表比较(按元素逐个比较)
print([1, 2, 3] < [1, 2, 4]) # True
print([1, 2, 3] < [1, 2]) # False
# 5. 过滤列表
numbers = [1, 2, 3, 4, 5, 6]
filtered = list(filter(lambda x: x % 2 == 0, numbers))
print(f"过滤偶数: {filtered}")
# 6. 映射列表
mapped = list(map(lambda x: x * 2, numbers))
print(f"映射加倍: {mapped}")
# 7. zip多个列表
names = ['Alice', 'Bob', 'Charlie']
ages = [25, 30, 35]
for name, age in zip(names, ages):
print(f"{name} is {age} years old")
# 8. 使用any()和all()
print(any(x > 5 for x in [1, 3, 5, 7])) # True
print(all(x > 5 for x in [1, 3, 5, 7])) # False
2.8 多维列表(嵌套列表)
python
# 1. 创建二维列表(矩阵)
matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
# 2. 访问元素
print(f"矩阵[1][2]: {matrix[1][2]}") # 6
# 3. 遍历二维列表
print("逐行遍历:")
for row in matrix:
print(row)
print("逐个元素遍历:")
for row in matrix:
for element in row:
print(element, end=' ')
print()
# 4. 列表推导式创建二维列表
matrix_5x5 = [[0 for _ in range(5)] for _ in range(5)]
print(f"5x5零矩阵: {matrix_5x5}")
# 5. 注意事项:错误的方式创建多维列表
wrong_matrix = [[0] * 5] * 3 # 这种方式会创建共享的引用
wrong_matrix[0][0] = 1
print(f"错误的多维列表创建: {wrong_matrix}") # 所有行的第一列都变成了1
2.9 性能注意事项
python
import time
# 1. append() vs insert(0)
def test_performance():
n = 10000
# 在末尾添加元素 - O(1)
start = time.time()
lst = []
for i in range(n):
lst.append(i)
end = time.time()
print(f"append() 耗时: {end-start:.6f}秒")
# 在开头插入元素 - O(n)
start = time.time()
lst = []
for i in range(n):
lst.insert(0, i)
end = time.time()
print(f"insert(0) 耗时: {end-start:.6f}秒")
test_performance()
# 2. 成员检查性能比较
def membership_test():
lst = list(range(10000))
s = set(range(10000))
# 列表查找 - O(n)
start = time.time()
print(9999 in lst) # 最坏情况
end = time.time()
print(f"列表成员检查耗时: {end-start:.6f}秒")
# 集合查找 - O(1)
start = time.time()
print(9999 in s)
end = time.time()
print(f"集合成员检查耗时: {end-start:.6f}秒")
membership_test()
2.10 实用示例
python
# 1. 去重(保持顺序)
def deduplicate(lst):
seen = set()
result = []
for item in lst:
if item not in seen:
seen.add(item)
result.append(item)
return result
numbers = [1, 2, 2, 3, 4, 4, 5, 1, 2]
print(f"去重后: {deduplicate(numbers)}")
# 2. 统计频率
def frequency_counter(lst):
freq = {}
for item in lst:
freq[item] = freq.get(item, 0) + 1
return freq
words = ['apple', 'banana', 'apple', 'cherry', 'banana', 'apple']
print(f"频率统计: {frequency_counter(words)}")
# 3. 列表分块
def chunk_list(lst, chunk_size):
return [lst[i:i+chunk_size] for i in range(0, len(lst), chunk_size)]
numbers = list(range(10))
print(f"分块 (大小3): {chunk_list(numbers, 3)}")
# 4. 列表旋转
def rotate_list(lst, k):
k = k % len(lst) # 处理k大于列表长度的情况
return lst[-k:] + lst[:-k]
print(f"旋转列表 [1,2,3,4,5] (k=2): {rotate_list([1,2,3,4,5], 2)}")