bytes() - 字节对象构造函数

创建不可变的字节序列对象

分类: builtins 难度: 中级 更新: 2024-01-15
字节 二进制 编码 数据类型

bytes() - 字节对象构造函数

📝 概述

bytes() 是 Python 中的内置函数,用于创建不可变的字节序列对象。字节对象是由 0-255 范围内的整数组成的序列,主要用于处理二进制数据、文件 I/O、网络通信、编码转换等场景。与字符串不同,字节对象直接表示原始的二进制数据。

🎯 学习目标

  • 掌握 bytes()函数的基本用法和语法
  • 理解字节对象与字符串的区别和联系
  • 学会字节对象的编码和解码操作
  • 了解字节对象在文件处理和网络编程中的应用
  • 掌握字节对象的常用方法和操作

📋 前置知识

  • Python 基本语法
  • 字符串的基本概念和操作
  • 编码(如 UTF-8、ASCII)的基本概念
  • 二进制和十六进制数的基本知识
  • 可迭代对象的概念

🔍 详细内容

基本概念

字节对象(bytes)是不可变的字节序列,每个元素都是 0-255 范围内的整数。它是 Python 中处理二进制数据的主要数据类型,与字符串类似但专门用于二进制数据。

语法格式

bytes([source[, encoding[, errors]]])

参数说明

参数名 类型 必需 默认值 说明
source 多种类型 数据源:字符串、可迭代对象、整数或缓冲区对象
encoding 字符串 当 source 为字符串时的编码方式
errors 字符串 ‘strict’ 编码错误的处理方式

返回值

  • 类型: bytes 对象
  • 内容: 不可变的字节序列

💡 代码示例

基本用法

## 创建空的字节对象
empty_bytes = bytes()
print(empty_bytes)  # 输出: b''
print(type(empty_bytes))  # 输出: <class 'bytes'>
print(len(empty_bytes))  # 输出: 0

## 从整数创建指定长度的零字节
zero_bytes = bytes(5)
print(zero_bytes)  # 输出: b'\x00\x00\x00\x00\x00'
print(len(zero_bytes))  # 输出: 5

## 从整数列表创建字节对象
int_list = [65, 66, 67, 68, 69]  # ASCII 码
bytes_from_list = bytes(int_list)
print(bytes_from_list)  # 输出: b'ABCDE'

## 从范围对象创建字节对象
bytes_from_range = bytes(range(65, 70))
print(bytes_from_range)  # 输出: b'ABCDE'

## 字节字面量
literal_bytes = b'Hello, World!'
print(literal_bytes)  # 输出: b'Hello, World!'
print(type(literal_bytes))  # 输出: <class 'bytes'>

从字符串创建字节对象

## 从字符串创建字节对象(需要指定编码)
text = "Hello, 世界!"

## UTF-8 编码
utf8_bytes = bytes(text, 'utf-8')
print(f"UTF-8 编码: {utf8_bytes}")
print(f"长度: {len(utf8_bytes)}字节")

## ASCII 编码(会出错,因为包含非 ASCII 字符)
try:
    ascii_bytes = bytes(text, 'ascii')
except UnicodeEncodeError as e:
    print(f"ASCII 编码错误: {e}")

## 使用错误处理
ascii_bytes_ignore = bytes(text, 'ascii', errors='ignore')
print(f"ASCII 编码(忽略错误): {ascii_bytes_ignore}")

ascii_bytes_replace = bytes(text, 'ascii', errors='replace')
print(f"ASCII 编码(替换错误): {ascii_bytes_replace}")

## 不同编码的比较
text_simple = "Hello"
print(f"原文本: {text_simple}")
print(f"UTF-8: {bytes(text_simple, 'utf-8')}")
print(f"ASCII: {bytes(text_simple, 'ascii')}")
print(f"Latin-1: {bytes(text_simple, 'latin-1')}")

字节对象的基本操作

## 字节对象的基本操作
data = b'Hello, World!'

## 长度
print(f"长度: {len(data)}")

## 索引访问
print(f"第一个字节: {data[0]} (字符: {chr(data[0])})")
print(f"最后一个字节: {data[-1]} (字符: {chr(data[-1])})")

## 切片
print(f"前 5 个字节: {data[:5]}")
print(f"后 6 个字节: {data[-6:]}")
print(f"每隔 2 个字节: {data[::2]}")

## 遍历字节对象
print("遍历字节值:")
for i, byte_val in enumerate(data[:5]):
    print(f"  索引{i}: {byte_val} (0x{byte_val:02x}) '{chr(byte_val)}'")

## 检查是否包含某个字节或子序列
print(f"包含字节 72(H): {72 in data}")
print(f"包含子序列 b'World': {b'World' in data}")
print(f"包含子序列 b'Python': {b'Python' in data}")

## 查找
print(f"'World'的位置: {data.find(b'World')}")
print(f"'o'的位置: {data.find(b'o')}")
print(f"'xyz'的位置: {data.find(b'xyz')}")

字节对象的方法

## 字节对象的常用方法
data = b'Hello, World! Hello, Python!'

## 大小写转换
print(f"原始: {data}")
print(f"大写: {data.upper()}")
print(f"小写: {data.lower()}")
print(f"标题: {data.title()}")

## 替换
replaced = data.replace(b'Hello', b'Hi')
print(f"替换后: {replaced}")

## 分割
split_result = data.split(b' ')
print(f"按空格分割: {split_result}")

split_comma = data.split(b',')
print(f"按逗号分割: {split_comma}")

## 连接
parts = [b'Python', b'is', b'awesome']
joined = b' '.join(parts)
print(f"连接结果: {joined}")

## 去除空白
padded_data = b'  Hello, World!  '
print(f"原始(带空格): {repr(padded_data)}")
print(f"去除空白: {repr(padded_data.strip())}")
print(f"去除左空白: {repr(padded_data.lstrip())}")
print(f"去除右空白: {repr(padded_data.rstrip())}")

## 判断方法
test_data = b'12345'
print(f"是否全为数字: {test_data.isdigit()}")
print(f"是否全为字母: {test_data.isalpha()}")
print(f"是否全为字母数字: {test_data.isalnum()}")

test_alpha = b'Hello'
print(f"'{test_alpha}'是否全为字母: {test_alpha.isalpha()}")

🚀 高级应用

编码和解码

## 编码和解码示例
original_text = "Python 编程:从入门到精通"
print(f"原始文本: {original_text}")

## 编码为不同格式
encodings = ['utf-8', 'utf-16', 'utf-32', 'gbk']

for encoding in encodings:
    try:
        encoded = original_text.encode(encoding)
        print(f"\n{encoding}编码:")
        print(f"  字节对象: {encoded}")
        print(f"  长度: {len(encoded)}字节")
        print(f"  十六进制: {encoded.hex()}")
        
#        # 解码回文本
        decoded = encoded.decode(encoding)
        print(f"  解码结果: {decoded}")
        print(f"  解码正确: {decoded == original_text}")
        
    except UnicodeEncodeError as e:
        print(f"{encoding}编码失败: {e}")

## 处理编码错误
problematic_text = "Hello 🌍 World"
print(f"\n 问题文本: {problematic_text}")

## 不同的错误处理策略
error_strategies = ['strict', 'ignore', 'replace', 'xmlcharrefreplace']

for strategy in error_strategies:
    try:
        encoded = problematic_text.encode('ascii', errors=strategy)
        print(f"ASCII 编码({strategy}): {encoded}")
    except UnicodeEncodeError as e:
        print(f"ASCII 编码({strategy})失败: {e}")

二进制文件处理

import os
import tempfile

## 二进制文件读写示例
def binary_file_demo():
    """二进制文件处理演示"""
#    # 创建临时文件
    with tempfile.NamedTemporaryFile(delete=False) as temp_file:
        temp_filename = temp_file.name
    
    try:
#        # 准备二进制数据
        header = b'\x89PNG\r\n\x1a\n'  # PNG 文件头
        data = b'This is binary data: ' + bytes(range(256))
        footer = b'\x00\x00\x00\x00IEND\xaeB`\x82'  # PNG 文件尾
        
        full_data = header + data + footer
        
#        # 写入二进制文件
        with open(temp_filename, 'wb') as f:
            f.write(full_data)
        
        print(f"写入了 {len(full_data)} 字节到文件")
        
#        # 读取二进制文件
        with open(temp_filename, 'rb') as f:
            read_data = f.read()
        
        print(f"从文件读取了 {len(read_data)} 字节")
        print(f"数据一致: {read_data == full_data}")
        
#        # 分析文件头
        print(f"\n 文件头分析:")
        print(f"  前 8 字节: {read_data[:8]}")
        print(f"  十六进制: {read_data[:8].hex()}")
        print(f"  是否为 PNG: {read_data.startswith(b'\x89PNG')}")
        
#        # 查找特定模式
        pattern = b'binary data'
        position = read_data.find(pattern)
        if position != -1:
            print(f"  找到模式'{pattern.decode()}'在位置: {position}")
        
    finally:
#        # 清理临时文件
        if os.path.exists(temp_filename):
            os.unlink(temp_filename)

binary_file_demo()

网络数据处理

import struct
import socket
from datetime import datetime

## 网络协议数据包构造
class NetworkPacket:
    """简单的网络数据包类"""
    
    def __init__(self, packet_type, sequence, timestamp, payload):
        self.packet_type = packet_type
        self.sequence = sequence
        self.timestamp = timestamp
        self.payload = payload.encode('utf-8') if isinstance(payload, str) else payload
    
    def pack(self):
        """将数据包打包为字节序列"""
#        # 包头格式: 类型(1 字节) + 序列号(4 字节) + 时间戳(8 字节) + 载荷长度(4 字节)
        header = struct.pack('!BIQi', 
                           self.packet_type,
                           self.sequence, 
                           int(self.timestamp),
                           len(self.payload))
        return header + self.payload
    
    @classmethod
    def unpack(cls, data):
        """从字节序列解包数据包"""
        if len(data) < 17:  # 最小包头长度
            raise ValueError("数据包太短")
        
#        # 解包包头
        packet_type, sequence, timestamp, payload_length = struct.unpack('!BIQi', data[:17])
        
#        # 检查载荷长度
        if len(data) < 17 + payload_length:
            raise ValueError("载荷数据不完整")
        
#        # 提取载荷
        payload = data[17:17+payload_length]
        
        return cls(packet_type, sequence, timestamp, payload)
    
    def __str__(self):
        return f"Packet(type={self.packet_type}, seq={self.sequence}, time={self.timestamp}, payload={len(self.payload)}bytes)"

## 网络数据包示例
print("网络数据包处理示例:")

## 创建数据包
packet1 = NetworkPacket(1, 12345, datetime.now().timestamp(), "Hello, Network!")
packet2 = NetworkPacket(2, 12346, datetime.now().timestamp(), b"\x01\x02\x03\x04")

print(f"原始数据包 1: {packet1}")
print(f"原始数据包 2: {packet2}")

## 打包
packed1 = packet1.pack()
packed2 = packet2.pack()

print(f"\n 打包后:")
print(f"  数据包 1: {len(packed1)}字节, 十六进制: {packed1.hex()[:40]}...")
print(f"  数据包 2: {len(packed2)}字节, 十六进制: {packed2.hex()}")

## 解包
unpacked1 = NetworkPacket.unpack(packed1)
unpacked2 = NetworkPacket.unpack(packed2)

print(f"\n 解包后:")
print(f"  数据包 1: {unpacked1}")
print(f"  数据包 2: {unpacked2}")

## 验证数据完整性
print(f"\n 数据完整性验证:")
print(f"  包 1 载荷一致: {packet1.payload == unpacked1.payload}")
print(f"  包 2 载荷一致: {packet2.payload == unpacked2.payload}")

## 模拟网络传输
def simulate_network_transmission(packets):
    """模拟网络传输"""
#    # 将多个数据包合并
    combined_data = b''
    for packet in packets:
        packed = packet.pack()
        combined_data += packed
    
    print(f"\n 模拟网络传输:")
    print(f"  总数据长度: {len(combined_data)}字节")
    
#    # 模拟接收和解析
    received_packets = []
    offset = 0
    
    while offset < len(combined_data):
        try:
            packet = NetworkPacket.unpack(combined_data[offset:])
            received_packets.append(packet)
            
#            # 计算下一个数据包的偏移
            packet_size = 17 + len(packet.payload)
            offset += packet_size
            
        except ValueError as e:
            print(f"  解析错误: {e}")
            break
    
    print(f"  成功接收 {len(received_packets)} 个数据包")
    return received_packets

## 测试网络传输模拟
test_packets = [packet1, packet2]
received = simulate_network_transmission(test_packets)

数据序列化和反序列化

import json
import pickle
import base64
from datetime import datetime

## 复杂数据结构的序列化
class DataSerializer:
    """数据序列化工具类"""
    
    @staticmethod
    def serialize_json(data):
        """JSON 序列化(文本格式)"""
        json_str = json.dumps(data, ensure_ascii=False, default=str)
        return json_str.encode('utf-8')
    
    @staticmethod
    def deserialize_json(data_bytes):
        """JSON 反序列化"""
        json_str = data_bytes.decode('utf-8')
        return json.loads(json_str)
    
    @staticmethod
    def serialize_pickle(data):
        """Pickle 序列化(二进制格式)"""
        return pickle.dumps(data)
    
    @staticmethod
    def deserialize_pickle(data_bytes):
        """Pickle 反序列化"""
        return pickle.loads(data_bytes)
    
    @staticmethod
    def serialize_base64(data):
        """Base64 编码"""
        if isinstance(data, str):
            data = data.encode('utf-8')
        return base64.b64encode(data)
    
    @staticmethod
    def deserialize_base64(data_bytes):
        """Base64 解码"""
        return base64.b64decode(data_bytes)

## 测试数据
test_data = {
    'name': '张三',
    'age': 30,
    'scores': [85, 92, 78],
    'metadata': {
        'created': datetime.now(),
        'tags': ['student', 'python', '编程']
    },
    'binary_data': bytes(range(10))
}

print("数据序列化示例:")
print(f"原始数据: {test_data}")

## JSON 序列化(需要处理不可序列化的类型)
json_serializable_data = {
    'name': test_data['name'],
    'age': test_data['age'],
    'scores': test_data['scores'],
    'metadata': {
        'created': test_data['metadata']['created'].isoformat(),
        'tags': test_data['metadata']['tags']
    },
    'binary_data': test_data['binary_data'].hex()  # 转换为十六进制字符串
}

json_bytes = DataSerializer.serialize_json(json_serializable_data)
print(f"\nJSON 序列化:")
print(f"  长度: {len(json_bytes)}字节")
print(f"  内容: {json_bytes.decode('utf-8')[:100]}...")

## JSON 反序列化
json_restored = DataSerializer.deserialize_json(json_bytes)
print(f"  反序列化: {json_restored['name']}, {json_restored['age']}")

## Pickle 序列化(可以处理任意 Python 对象)
pickle_bytes = DataSerializer.serialize_pickle(test_data)
print(f"\nPickle 序列化:")
print(f"  长度: {len(pickle_bytes)}字节")
print(f"  十六进制: {pickle_bytes.hex()[:50]}...")

## Pickle 反序列化
pickle_restored = DataSerializer.deserialize_pickle(pickle_bytes)
print(f"  反序列化成功: {pickle_restored['name']}")
print(f"  日期对象: {pickle_restored['metadata']['created']}")
print(f"  二进制数据: {pickle_restored['binary_data']}")

## Base64 编码
original_binary = b"\x89PNG\r\n\x1a\n 这是一些二进制数据"
base64_encoded = DataSerializer.serialize_base64(original_binary)
print(f"\nBase64 编码:")
print(f"  原始: {original_binary}")
print(f"  编码: {base64_encoded}")
print(f"  编码字符串: {base64_encoded.decode('ascii')}")

## Base64 解码
base64_decoded = DataSerializer.deserialize_base64(base64_encoded)
print(f"  解码: {base64_decoded}")
print(f"  一致性: {original_binary == base64_decoded}")

⚠️ 常见陷阱与最佳实践

编码问题

## 常见编码问题和解决方案

## 问题 1:忘记指定编码
text = "Hello, 世界!"
try:
#    # 错误:没有指定编码
    wrong_bytes = bytes(text)  # TypeError
except TypeError as e:
    print(f"错误 1: {e}")

## 正确做法
correct_bytes = bytes(text, 'utf-8')
print(f"正确: {correct_bytes}")

## 问题 2:编码不匹配
utf8_bytes = "中文".encode('utf-8')
print(f"UTF-8 字节: {utf8_bytes}")

try:
#    # 错误:用错误的编码解码
    wrong_decode = utf8_bytes.decode('gbk')
except UnicodeDecodeError as e:
    print(f"错误 2: {e}")

## 正确做法
correct_decode = utf8_bytes.decode('utf-8')
print(f"正确解码: {correct_decode}")

## 问题 3:处理不完整的字节序列
incomplete_utf8 = b'\xe4\xb8\xad'  # "中"的 UTF-8 编码的前 3 字节中的 3 字节
print(f"完整 UTF-8: {incomplete_utf8}")
print(f"解码: {incomplete_utf8.decode('utf-8')}")

## 不完整的序列
incomplete = b'\xe4\xb8'  # 缺少最后一个字节
try:
    incomplete.decode('utf-8')
except UnicodeDecodeError as e:
    print(f"错误 3: {e}")

## 使用错误处理
print(f"忽略错误: {incomplete.decode('utf-8', errors='ignore')}")
print(f"替换错误: {incomplete.decode('utf-8', errors='replace')}")

性能优化

import time

## 字节对象性能优化
def performance_comparison():
    """性能比较"""
    n = 100000
    
#    # 方法 1:逐个添加(低效)
    start = time.time()
    result1 = b''
    for i in range(n):
        result1 += bytes([i % 256])
    time1 = time.time() - start
    
#    # 方法 2:使用列表然后转换(高效)
    start = time.time()
    byte_list = []
    for i in range(n):
        byte_list.append(i % 256)
    result2 = bytes(byte_list)
    time2 = time.time() - start
    
#    # 方法 3:使用生成器表达式(最高效)
    start = time.time()
    result3 = bytes(i % 256 for i in range(n))
    time3 = time.time() - start
    
    print(f"性能比较({n}个字节):")
    print(f"  逐个添加: {time1:.4f}秒")
    print(f"  列表转换: {time2:.4f}秒")
    print(f"  生成器: {time3:.4f}秒")
    print(f"  结果一致: {result1 == result2 == result3}")
    print(f"  最快方法比最慢快: {time1 / time3:.1f}倍")

performance_comparison()

## 大文件处理优化
def efficient_file_processing():
    """高效的文件处理"""
    import tempfile
    import os
    
#    # 创建大文件
    with tempfile.NamedTemporaryFile(delete=False) as temp_file:
        temp_filename = temp_file.name
#        # 写入 1MB 数据
        data = bytes(range(256)) * 4096  # 1MB
        temp_file.write(data)
    
    try:
#        # 方法 1:一次性读取(内存消耗大)
        start = time.time()
        with open(temp_filename, 'rb') as f:
            all_data = f.read()
        time1 = time.time() - start
        
#        # 方法 2:分块读取(内存友好)
        start = time.time()
        chunk_size = 8192  # 8KB 块
        processed_size = 0
        with open(temp_filename, 'rb') as f:
            while True:
                chunk = f.read(chunk_size)
                if not chunk:
                    break
                processed_size += len(chunk)
#                # 处理块数据(这里只是计数)
        time2 = time.time() - start
        
        print(f"\n 文件处理性能:")
        print(f"  文件大小: {len(data)}字节")
        print(f"  一次性读取: {time1:.4f}秒")
        print(f"  分块读取: {time2:.4f}秒")
        print(f"  处理大小一致: {len(all_data) == processed_size}")
        
    finally:
        os.unlink(temp_filename)

efficient_file_processing()

内存管理

import sys
import gc

## 内存使用分析
def memory_analysis():
    """内存使用分析"""
#    # 不同大小的字节对象
    sizes = [100, 1000, 10000, 100000]
    
    print("字节对象内存使用分析:")
    for size in sizes:
#        # 创建字节对象
        data = bytes(range(256)) * (size // 256 + 1)
        data = data[:size]  # 截取到指定大小
        
#        # 测量内存使用
        obj_size = sys.getsizeof(data)
        overhead = obj_size - size
        
        print(f"  {size}字节数据:")
        print(f"    对象大小: {obj_size}字节")
        print(f"    开销: {overhead}字节 ({overhead/size*100:.1f}%)")
    
#    # 字节对象 vs 字符串内存比较
    text = "Hello, World!" * 1000
    text_bytes = text.encode('utf-8')
    
    print(f"\n 字符串 vs 字节对象:")
    print(f"  字符串: {sys.getsizeof(text)}字节")
    print(f"  字节对象: {sys.getsizeof(text_bytes)}字节")
    print(f"  字符串长度: {len(text)}字符")
    print(f"  字节对象长度: {len(text_bytes)}字节")

memory_analysis()

## 内存泄漏预防
def prevent_memory_leaks():
    """预防内存泄漏"""
    print("\n 内存泄漏预防示例:")
    
#    # 问题:循环引用
    class DataProcessor:
        def __init__(self):
            self.data = b''
            self.callbacks = []
        
        def add_callback(self, callback):
            self.callbacks.append(callback)
        
        def process(self, new_data):
            self.data += new_data
            for callback in self.callbacks:
                callback(self.data)
    
#    # 创建处理器
    processor = DataProcessor()
    
#    # 添加回调(可能造成循环引用)
    def callback(data):
#        # 这个回调持有对 processor 的引用
        print(f"处理了 {len(data)} 字节")
    
    processor.add_callback(callback)
    
#    # 处理数据
    for i in range(5):
        processor.process(bytes([i] * 100))
    
#    # 清理(重要!)
    processor.callbacks.clear()
    del processor
    gc.collect()  # 强制垃圾回收
    
    print("  已清理资源")

prevent_memory_leaks()

🔧 实际应用场景

图像处理

## 简单的图像数据处理
class SimpleImage:
    """简单的图像类(演示用)"""
    
    def __init__(self, width, height, channels=3):
        self.width = width
        self.height = height
        self.channels = channels
#        # 创建空白图像数据
        self.data = bytes(width * height * channels)
    
    def set_pixel(self, x, y, color):
        """设置像素颜色"""
        if 0 <= x < self.width and 0 <= y < self.height:
            offset = (y * self.width + x) * self.channels
#            # 转换为可变的 bytearray 进行修改
            data_array = bytearray(self.data)
            for i, c in enumerate(color[:self.channels]):
                data_array[offset + i] = c
            self.data = bytes(data_array)
    
    def get_pixel(self, x, y):
        """获取像素颜色"""
        if 0 <= x < self.width and 0 <= y < self.height:
            offset = (y * self.width + x) * self.channels
            return tuple(self.data[offset:offset + self.channels])
        return None
    
    def save_ppm(self, filename):
        """保存为 PPM 格式(简单的图像格式)"""
        with open(filename, 'wb') as f:
#            # PPM 头部
            header = f"P6\n{self.width} {self.height}\n255\n".encode('ascii')
            f.write(header)
#            # 图像数据
            f.write(self.data)
    
    @classmethod
    def load_ppm(cls, filename):
        """从 PPM 文件加载"""
        with open(filename, 'rb') as f:
#            # 读取头部
            magic = f.readline().strip()
            if magic != b'P6':
                raise ValueError("不是 P6 PPM 文件")
            
#            # 跳过注释
            line = f.readline()
            while line.startswith(b'#'):
                line = f.readline()
            
#            # 解析尺寸
            width, height = map(int, line.split())
            
#            # 读取最大值
            max_val = int(f.readline().strip())
            if max_val != 255:
                raise ValueError("只支持 8 位 PPM 文件")
            
#            # 读取图像数据
            data = f.read()
            
#            # 创建图像对象
            image = cls(width, height)
            image.data = data
            return image

## 创建简单图像
print("图像处理示例:")
image = SimpleImage(100, 100)

## 绘制简单图案
for x in range(100):
    for y in range(100):
#        # 创建渐变效果
        r = (x * 255) // 100
        g = (y * 255) // 100
        b = 128
        image.set_pixel(x, y, (r, g, b))

## 检查几个像素
print(f"像素(0,0): {image.get_pixel(0, 0)}")
print(f"像素(50,50): {image.get_pixel(50, 50)}")
print(f"像素(99,99): {image.get_pixel(99, 99)}")
print(f"图像数据大小: {len(image.data)}字节")

加密和哈希

import hashlib
import hmac
import secrets

## 加密和哈希示例
class CryptoUtils:
    """加密工具类"""
    
    @staticmethod
    def hash_data(data, algorithm='sha256'):
        """计算数据哈希"""
        if isinstance(data, str):
            data = data.encode('utf-8')
        
        hasher = hashlib.new(algorithm)
        hasher.update(data)
        return hasher.digest()
    
    @staticmethod
    def hash_file(filename, algorithm='sha256', chunk_size=8192):
        """计算文件哈希"""
        hasher = hashlib.new(algorithm)
        with open(filename, 'rb') as f:
            while True:
                chunk = f.read(chunk_size)
                if not chunk:
                    break
                hasher.update(chunk)
        return hasher.digest()
    
    @staticmethod
    def hmac_sign(data, key, algorithm='sha256'):
        """HMAC 签名"""
        if isinstance(data, str):
            data = data.encode('utf-8')
        if isinstance(key, str):
            key = key.encode('utf-8')
        
        return hmac.new(key, data, algorithm).digest()
    
    @staticmethod
    def simple_xor_encrypt(data, key):
        """简单 XOR 加密(仅用于演示)"""
        if isinstance(data, str):
            data = data.encode('utf-8')
        if isinstance(key, str):
            key = key.encode('utf-8')
        
#        # 扩展密钥到数据长度
        extended_key = (key * (len(data) // len(key) + 1))[:len(data)]
        
#        # XOR 操作
        encrypted = bytes(a ^ b for a, b in zip(data, extended_key))
        return encrypted
    
    @staticmethod
    def generate_salt(length=32):
        """生成随机盐值"""
        return secrets.token_bytes(length)

## 加密示例
print("加密和哈希示例:")

## 数据哈希
original_data = "这是需要哈希的重要数据"
sha256_hash = CryptoUtils.hash_data(original_data)
md5_hash = CryptoUtils.hash_data(original_data, 'md5')

print(f"原始数据: {original_data}")
print(f"SHA256 哈希: {sha256_hash.hex()}")
print(f"MD5 哈希: {md5_hash.hex()}")

## HMAC 签名
secret_key = "my_secret_key"
signature = CryptoUtils.hmac_sign(original_data, secret_key)
print(f"HMAC 签名: {signature.hex()}")

## 验证签名
verify_signature = CryptoUtils.hmac_sign(original_data, secret_key)
print(f"签名验证: {signature == verify_signature}")

## 简单加密
encryption_key = "encryption_key_123"
encrypted_data = CryptoUtils.simple_xor_encrypt(original_data, encryption_key)
print(f"加密数据: {encrypted_data.hex()}")

## 解密(XOR 加密是对称的)
decrypted_data = CryptoUtils.simple_xor_encrypt(encrypted_data, encryption_key)
print(f"解密数据: {decrypted_data.decode('utf-8')}")
print(f"解密正确: {decrypted_data.decode('utf-8') == original_data}")

## 生成随机盐值
salt = CryptoUtils.generate_salt()
print(f"随机盐值: {salt.hex()}")

## 密码哈希(加盐)
password = "user_password_123"
salted_password = salt + password.encode('utf-8')
password_hash = CryptoUtils.hash_data(salted_password)
print(f"加盐密码哈希: {password_hash.hex()}")

🔗 相关函数

内置函数

  • bytearray() - 创建可变字节数组
  • str() - 字符串构造函数
  • int() - 整数转换函数
  • len() - 获取长度
  • iter() - 创建迭代器
  • memoryview() - 创建内存视图

标准库模块

  • codecs - 编解码器
    • encode(), decode() - 编码解码
    • open() - 编码文件操作
  • base64 - Base64 编码
    • b64encode(), b64decode() - Base64 编解码
    • urlsafe_b64encode() - URL 安全编码
  • binascii - 二进制和 ASCII 转换
    • hexlify(), unhexlify() - 十六进制转换
    • crc32() - CRC32 校验
  • struct - 二进制数据结构
    • pack(), unpack() - 数据打包解包
  • hashlib - 哈希算法
    • md5(), sha256() - 哈希函数
  • hmac - HMAC 算法
  • secrets - 安全随机数

第三方库

  • cryptography - 现代加密库
  • Pillow - 图像处理
  • numpy - 数值计算
    • np.frombuffer() - 从字节创建数组
    • np.tobytes() - 转换为字节

📚 扩展阅读

🏷️ 标签

字节 二进制 编码 数据类型 文件处理 网络编程


最后更新: 2024-01-15
作者: Python 文档工程师
版本: 1.0

作者: Python 文档工程师

版本: 1.0

讨论与反馈

欢迎在下方留言讨论,分享你的学习心得或提出问题。评论基于GitHub Issues,需要GitHub账号。