Python位运算实战指南:二进制基础、权限系统与性能优化
很多Python初学者看到&、|、^、<<、>>这些运算符时,会觉得业务代码用不上。实际上位运算在权限系统设计、颜色处理、状态标记、网络编程、数据压缩与加密中无处不在,而且比算术运算快得多。理解位运算能让你真正理解计算机如何看待数据——底层一切都是0和1。本文从二进制基础开始,逐步掌握Python中所有位运算符的使用方法和实战场景。
class Permission:
"""基于位运算的权限系统"""
READ = 1 << 0 # 0b000001 = 1
WRITE = 1 << 1 # 0b000010 = 2
EXECUTE = 1 << 2 # 0b000100 = 4
DELETE = 1 << 3 # 0b001000 = 8
ADMIN = 1 << 4 # 0b010000 = 16
@staticmethod
def has_permission(user_perm, perm):
return (user_perm & perm) != 0
@staticmethod
def grant(user_perm, perm):
return user_perm | perm
@staticmethod
def revoke(user_perm, perm):
return user_perm & (~perm)
@staticmethod
def toggle(user_perm, perm):
return user_perm ^ perm
@staticmethod
def permission_names(perm_value):
names = []
for name in ['READ', 'WRITE', 'EXECUTE', 'DELETE', 'ADMIN']:
if perm_value & getattr(Permission, name):
names.append(name)
return names
二进制基础
计算机用二进制存储数据,因为只有开/关两种状态物理上最可靠。Python中用0b或0B前缀表示二进制数。
a = 0b1010 # 二进制1010 = 十进制10
b = 0b1111 # 二进制1111 = 十进制15
print(a) # 10
print(bin(10)) # 0b1010
print(format(10, 'b')) # 1010
print(format(255, '08b')) # 11111111
# 手动转换:十进制→二进制
def decimal_to_binary(n):
if n == 0:
return '0'
bits = []
while n > 0:
bits.append(str(n % 2))
n //= 2
return ''.join(reversed(bits))
print(decimal_to_binary(10)) # 1010
# 二进制→十进制
def binary_to_decimal(binary_str):
result = 0
for bit in binary_str:
result = result * 2 + int(bit)
return result
print(binary_to_decimal('1010')) # 10
一位(bit)是二进制的一位;一个字节(byte)是8个比特。位从右往左编号,权重为2的n次方。
print((10).bit_length()) # 4
print((255).bit_length())# 8
Python还支持八进制(0o)、十六进制(0x)表示。
binary = 0b1010
hexadecimal = 0xFF
print(bin(255)) # 0b11111111
print(hex(255)) # 0xff
print(int('0xf', 16))# 15
# f-string格式化
n = 42
print(f"二进制: {n:b}, 八进制: {n:o}, 十六进制: {n:x}")
按位与 &
运算规则:两位都为1才得1。
a = 0b1100# 12
b = 0b1010# 10
print(a & b)# 8 (0b1000)
# 检查某一位是否为1
def is_bit_set(n, position):
return (n & (1 << position)) != 0
print(is_bit_set(0b1100, 2))# True
# 取低N位(掩码操作)
def low_n_bits(n, num_bits):
mask = (1 << num_bits) - 1
return n & mask
print(bin(low_n_bits(0b11010110, 4)))# 0b110
按位或 |
运算规则:任一位为1就得1。
a = 0b1100
b = 0b1010
print(a | b)# 14 (0b1110)
# 设置某一位为1
def set_bit(n, position):
return n | (1 << position)
print(bin(set_bit(0b1000, 1)))# 0b1010
# 合并标志位:权限系统的核心
READ = 0b001
WRITE = 0b010
EXECUTE = 0b100
permission = READ | WRITE # 3 (0b011)
print(permission)
按位异或 ^
运算规则:两位不同得1,相同得0。
a = 0b1100
b = 0b1010
print(a ^ b)# 6 (0b0110)
# 切换某一位(toggle)
def toggle_bit(n, position):
return n ^ (1 << position)
print(bin(toggle_bit(0b1010, 0)))# 0b1011
# 不使用临时变量交换整数
a, b = 10, 20
a ^= b
b ^= a
a ^= b
print(a, b)# 20, 10
# 找出数组中唯一出现奇数次的数
def find_odd_occurrence(arr):
result = 0
for num in arr:
result ^= num
return result
arr =
print(find_odd_occurrence(arr))# 5
# 简易异或加密
def xor_cipher(text, key):
return ''.join(chr(ord(c) ^ key) for c in text)
encrypted = xor_cipher("Hello", 42)
decrypted = xor_cipher(encrypted, 42)
print(decrypted)# Hello
按位取反 ~
Python中整数是无限精度的补码表示,~n = -(n+1)。
print(~10)# -11
print(~(-5)) # 4
# 固定位宽的取反需要掩码
def bitwise_not_fixed(n, num_bits=8):
mask = (1 << num_bits) - 1
return (~n) & mask
print(bin(bitwise_not_fixed(0b1100, 8)))# 0b11110011
左移 << 与右移 >>
左移一位相当于乘以2,右移一位相当于除以2(向下取整,左侧补符号位)。
x = 0b0001
print(bin(x << 2))# 0b100 (4)
print(1 << 10)# 1024
# 右移
x = 0b1000# 8
print(x >> 2)# 2 (0b10)
print(-16 >> 1)# -8
print(100 >> 2)# 25
# 提取特定位:右移+掩码
def get_bits(n, start, count):
return (n >> start) & ((1 << count) - 1)
print(bin(get_bits(0b10110110, 3, 3)))# 0b110
实战:颜色处理
def rgb_to_hex(r, g, b):
return f"#{(r << 16) | (g << 8) | b:06X}"
print(rgb_to_hex(255, 128, 0))# #FF8000
def hex_to_rgb(hex_color):
hex_color = hex_color.lstrip('#')
value = int(hex_color, 16)
r = (value >> 16) & 0xFF
g = (value >> 8) & 0xFF
b = value & 0xFF
return (r, g, b)
print(hex_to_rgb("#3498DB"))# (52, 152, 219)
实战:状态标记与位图
用一个整数表示多种状态的组合,并通过位运算快速检查/设置。
class UserStatus:
ONLINE = 1 << 0
VERIFIED = 1 << 1
PREMIUM = 1 << 2
BANNED = 1 << 3
MODERATOR = 1 << 4
@classmethod
def is_online(cls, status):
return (status & cls.ONLINE) != 0
@classmethod
def set_online(cls, status):
return status | cls.ONLINE
# 位图:批量追踪用户在线状态
class UserBitmap:
def __init__(self, max_users=1024):
self.bitmap_size = (max_users + 63) // 64
self.bitmap = * self.bitmap_size
def set_online(self, user_id):
word_idx = user_id // 64
bit_idx = user_id % 64
self.bitmap |= (1 << bit_idx)
def is_online(self, user_id):
word_idx = user_id // 64
bit_idx = user_id % 64
return (self.bitmap & (1 << bit_idx)) != 0
def online_count(self):
total = 0
for word in self.bitmap:
total += word.bit_count()# Python 3.8+
return total
性能优势
位运算比乘除法快很多。例如左移6位代替乘以64,右移代替除以2的幂。下面是用timeit测速的示例:
import timeit
n = 1234567890
t_multiply = timeit.timeit(lambda: n * 64, number=10_000_000)
t_shift = timeit.timeit(lambda: n << 6, number=10_000_000)
print(f"n * 64: {t_multiply:.4f}s")
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。
掌握这些位运算技巧,能让你写出更高效、更优雅的代码,尤其在系统编程、游戏开发、嵌入式等领域大显身手。
Re: Python位运算实战指南:二进制基础、权限系统与性能优化
感谢分享!位运算在权限系统和状态标记上的确非常高效,你给出的 `Permission` 类例子很清晰,正好展示了如何用少量代码实现灵活的权限组合。对于刚接触位运算的人来说,掩码和 toggle 这个概念可能有点绕,你用实际代码演示后就好理解多了。期待看到更多关于颜色处理或网络协议方向的应用实例!Re: Python位运算实战指南:二进制基础、权限系统与性能优化
楼主写得非常实用,尤其是那个Permission权限类,把位运算的经典应用讲得很清楚。之前做Web框架权限设计时,总有人用字符串或字典存权限,后来改成了这种位掩码方式,不仅判读快,存储也省。期待楼主后续能再聊聊位运算在图像处理和校验和里的实战思路,比如RGB通道的掩码提取、CRC这类场景,对新人非常有价值。Re: Python位运算实战指南:二进制基础、权限系统与性能优化
写得非常清晰!权限系统的示例很经典,把四个基本操作(添加、删除、切换、检查)都涵盖了,而且还展示了用位运算做状态标记的灵活性。我平时用 Python 写一些简单的配置项组合时,也常拿位运算来减少 if-else 的嵌套,尤其在需要同时管理多个布尔开关的场景下,感觉可读性和效率都提升了。 另外,你提到的“取低 N 位”那个 mask 技巧,在解析二进制协议时真的很实用。感谢分享,收藏了!
页:
[1]