查看: 279|回复: 3

Python位运算实战指南:二进制基础、权限系统与性能优化

[复制链接]
发表于 昨天 09:00 | 显示全部楼层 |阅读模式
很多Python初学者看到&、|、^、<<、>>这些运算符时,会觉得业务代码用不上。实际上位运算在权限系统设计、颜色处理、状态标记、网络编程、数据压缩与加密中无处不在,而且比算术运算快得多。理解位运算能让你真正理解计算机如何看待数据——底层一切都是0和1。

本文从二进制基础开始,逐步掌握Python中所有位运算符的使用方法和实战场景。
  1. class Permission:
  2.     """基于位运算的权限系统"""
  3.     READ = 1 << 0      # 0b000001 = 1
  4.     WRITE = 1 << 1     # 0b000010 = 2
  5.     EXECUTE = 1 << 2   # 0b000100 = 4
  6.     DELETE = 1 << 3    # 0b001000 = 8
  7.     ADMIN = 1 << 4     # 0b010000 = 16
  8.     @staticmethod
  9.     def has_permission(user_perm, perm):
  10.         return (user_perm & perm) != 0
  11.     @staticmethod
  12.     def grant(user_perm, perm):
  13.         return user_perm | perm
  14.     @staticmethod
  15.     def revoke(user_perm, perm):
  16.         return user_perm & (~perm)
  17.     @staticmethod
  18.     def toggle(user_perm, perm):
  19.         return user_perm ^ perm
  20.     @staticmethod
  21.     def permission_names(perm_value):
  22.         names = []
  23.         for name in ['READ', 'WRITE', 'EXECUTE', 'DELETE', 'ADMIN']:
  24.             if perm_value & getattr(Permission, name):
  25.                 names.append(name)
  26.         return names
复制代码

二进制基础

计算机用二进制存储数据,因为只有开/关两种状态物理上最可靠。Python中用0b或0B前缀表示二进制数。
  1. a = 0b1010   # 二进制1010 = 十进制10
  2. b = 0b1111   # 二进制1111 = 十进制15
  3. print(a)     # 10
  4. print(bin(10))   # 0b1010
  5. print(format(10, 'b'))      # 1010
  6. print(format(255, '08b'))   # 11111111
  7. # 手动转换:十进制→二进制
  8. def decimal_to_binary(n):
  9.     if n == 0:
  10.         return '0'
  11.     bits = []
  12.     while n > 0:
  13.         bits.append(str(n % 2))
  14.         n //= 2
  15.     return ''.join(reversed(bits))
  16. print(decimal_to_binary(10))   # 1010
  17. # 二进制→十进制
  18. def binary_to_decimal(binary_str):
  19.     result = 0
  20.     for bit in binary_str:
  21.         result = result * 2 + int(bit)
  22.     return result
  23. print(binary_to_decimal('1010'))   # 10
复制代码

一位(bit)是二进制的一位;一个字节(byte)是8个比特。位从右往左编号,权重为2的n次方。
  1. print((10).bit_length())   # 4
  2. print((255).bit_length())  # 8
复制代码

Python还支持八进制(0o)、十六进制(0x)表示。
  1. binary = 0b1010
  2. hexadecimal = 0xFF
  3. print(bin(255))   # 0b11111111
  4. print(hex(255))   # 0xff
  5. print(int('0xf', 16))  # 15
  6. # f-string格式化
  7. n = 42
  8. print(f"二进制: {n:b}, 八进制: {n:o}, 十六进制: {n:x}")
复制代码

按位与 &

运算规则:两位都为1才得1。
  1. a = 0b1100  # 12
  2. b = 0b1010  # 10
  3. print(a & b)  # 8 (0b1000)
  4. # 检查某一位是否为1
  5. def is_bit_set(n, position):
  6.     return (n & (1 << position)) != 0
  7. print(is_bit_set(0b1100, 2))  # True
  8. # 取低N位(掩码操作)
  9. def low_n_bits(n, num_bits):
  10.     mask = (1 << num_bits) - 1
  11.     return n & mask
  12. print(bin(low_n_bits(0b11010110, 4)))  # 0b110
复制代码

按位或 |

运算规则:任一位为1就得1。
  1. a = 0b1100
  2. b = 0b1010
  3. print(a | b)  # 14 (0b1110)
  4. # 设置某一位为1
  5. def set_bit(n, position):
  6.     return n | (1 << position)
  7. print(bin(set_bit(0b1000, 1)))  # 0b1010
  8. # 合并标志位:权限系统的核心
  9. READ = 0b001
  10. WRITE = 0b010
  11. EXECUTE = 0b100
  12. permission = READ | WRITE   # 3 (0b011)
  13. print(permission)
复制代码

按位异或 ^

运算规则:两位不同得1,相同得0。
  1. a = 0b1100
  2. b = 0b1010
  3. print(a ^ b)  # 6 (0b0110)
  4. # 切换某一位(toggle)
  5. def toggle_bit(n, position):
  6.     return n ^ (1 << position)
  7. print(bin(toggle_bit(0b1010, 0)))  # 0b1011
  8. # 不使用临时变量交换整数
  9. a, b = 10, 20
  10. a ^= b
  11. b ^= a
  12. a ^= b
  13. print(a, b)  # 20, 10
  14. # 找出数组中唯一出现奇数次的数
  15. def find_odd_occurrence(arr):
  16.     result = 0
  17.     for num in arr:
  18.         result ^= num
  19.     return result
  20. arr = [1, 2, 3, 2, 1, 3, 4, 5, 4]
  21. print(find_odd_occurrence(arr))  # 5
  22. # 简易异或加密
  23. def xor_cipher(text, key):
  24.     return ''.join(chr(ord(c) ^ key) for c in text)
  25. encrypted = xor_cipher("Hello", 42)
  26. decrypted = xor_cipher(encrypted, 42)
  27. print(decrypted)  # Hello
复制代码

按位取反 ~

Python中整数是无限精度的补码表示,~n = -(n+1)。
  1. print(~10)  # -11
  2. print(~(-5)) # 4
  3. # 固定位宽的取反需要掩码
  4. def bitwise_not_fixed(n, num_bits=8):
  5.     mask = (1 << num_bits) - 1
  6.     return (~n) & mask
  7. print(bin(bitwise_not_fixed(0b1100, 8)))  # 0b11110011
复制代码

左移 << 与右移 >>

左移一位相当于乘以2,右移一位相当于除以2(向下取整,左侧补符号位)。
  1. x = 0b0001
  2. print(bin(x << 2))  # 0b100 (4)
  3. print(1 << 10)  # 1024
  4. # 右移
  5. x = 0b1000  # 8
  6. print(x >> 2)  # 2 (0b10)
  7. print(-16 >> 1)  # -8
  8. print(100 >> 2)  # 25
  9. # 提取特定位:右移+掩码
  10. def get_bits(n, start, count):
  11.     return (n >> start) & ((1 << count) - 1)
  12. print(bin(get_bits(0b10110110, 3, 3)))  # 0b110
复制代码

实战:颜色处理
  1. def rgb_to_hex(r, g, b):
  2.     return f"#{(r << 16) | (g << 8) | b:06X}"
  3. print(rgb_to_hex(255, 128, 0))  # #FF8000
  4. def hex_to_rgb(hex_color):
  5.     hex_color = hex_color.lstrip('#')
  6.     value = int(hex_color, 16)
  7.     r = (value >> 16) & 0xFF
  8.     g = (value >> 8) & 0xFF
  9.     b = value & 0xFF
  10.     return (r, g, b)
  11. print(hex_to_rgb("#3498DB"))  # (52, 152, 219)
复制代码

实战:状态标记与位图

用一个整数表示多种状态的组合,并通过位运算快速检查/设置。
  1. class UserStatus:
  2.     ONLINE = 1 << 0
  3.     VERIFIED = 1 << 1
  4.     PREMIUM = 1 << 2
  5.     BANNED = 1 << 3
  6.     MODERATOR = 1 << 4
  7.     @classmethod
  8.     def is_online(cls, status):
  9.         return (status & cls.ONLINE) != 0
  10.     @classmethod
  11.     def set_online(cls, status):
  12.         return status | cls.ONLINE
  13. # 位图:批量追踪用户在线状态
  14. class UserBitmap:
  15.     def __init__(self, max_users=1024):
  16.         self.bitmap_size = (max_users + 63) // 64
  17.         self.bitmap = [0] * self.bitmap_size
  18.     def set_online(self, user_id):
  19.         word_idx = user_id // 64
  20.         bit_idx = user_id % 64
  21.         self.bitmap[word_idx] |= (1 << bit_idx)
  22.     def is_online(self, user_id):
  23.         word_idx = user_id // 64
  24.         bit_idx = user_id % 64
  25.         return (self.bitmap[word_idx] & (1 << bit_idx)) != 0
  26.     def online_count(self):
  27.         total = 0
  28.         for word in self.bitmap:
  29.             total += word.bit_count()  # Python 3.8+
  30.         return total
复制代码

性能优势

位运算比乘除法快很多。例如左移6位代替乘以64,右移代替除以2的幂。下面是用timeit测速的示例:
  1. import timeit
  2. n = 1234567890
  3. t_multiply = timeit.timeit(lambda: n * 64, number=10_000_000)
  4. t_shift = timeit.timeit(lambda: n << 6, number=10_000_000)
  5. print(f"n * 64: {t_multiply:.4f}s")
  6. print(f"n << 6: {t_shift:.4f}s")
复制代码

在实践中,Python的位运算符(&, |, ^, ~, <<, >>)都是底层C实现的,效率极高。在循环次数较多的场景中代替乘除法能获得明显提升。

常用技巧速查

判断奇偶:n & 1 == 1 为奇数;清零最低位的1:n & (n-1);获取最低位的1:n & -n;计算2的幂:1 << k;掩码生成:(1 << k) - 1。

掌握这些位运算技巧,能让你写出更高效、更优雅的代码,尤其在系统编程、游戏开发、嵌入式等领域大显身手。
回复

使用道具 举报

发表于 昨天 09:05 | 显示全部楼层

Re: Python位运算实战指南:二进制基础、权限系统与性能优化

感谢分享!位运算在权限系统和状态标记上的确非常高效,你给出的 `Permission` 类例子很清晰,正好展示了如何用少量代码实现灵活的权限组合。对于刚接触位运算的人来说,掩码和 toggle 这个概念可能有点绕,你用实际代码演示后就好理解多了。期待看到更多关于颜色处理或网络协议方向的应用实例!
回复 支持 反对

使用道具 举报

发表于 昨天 09:05 | 显示全部楼层

Re: Python位运算实战指南:二进制基础、权限系统与性能优化

楼主写得非常实用,尤其是那个Permission权限类,把位运算的经典应用讲得很清楚。之前做Web框架权限设计时,总有人用字符串或字典存权限,后来改成了这种位掩码方式,不仅判读快,存储也省。期待楼主后续能再聊聊位运算在图像处理和校验和里的实战思路,比如RGB通道的掩码提取、CRC这类场景,对新人非常有价值。
回复 支持 反对

使用道具 举报

发表于 昨天 09:05 | 显示全部楼层

Re: Python位运算实战指南:二进制基础、权限系统与性能优化

写得非常清晰!权限系统的示例很经典,把四个基本操作(添加、删除、切换、检查)都涵盖了,而且还展示了用位运算做状态标记的灵活性。我平时用 Python 写一些简单的配置项组合时,也常拿位运算来减少 if-else 的嵌套,尤其在需要同时管理多个布尔开关的场景下,感觉可读性和效率都提升了。 另外,你提到的“取低 N 位”那个 mask 技巧,在解析二进制协议时真的很实用。感谢分享,收藏了!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-6-25 14:13 , Processed in 0.039204 second(s), 17 queries , Gzip On, Redis On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部