优雅且高效的权限管理——利用位运算

Posted by Daniel's Blog on December 10, 2024

权限管理是开发中常见的场景,传统方法可能依赖数组、字典或数据库,尤其是在权限很多的情况下,大量的变量命名以及重复运用会增加代码的复杂度,而且更容易出错。今天分享如何用 位运算 来管理权限,包括 赋予移除检查 操作。

什么是位运算?

位运算是直接对整数的二进制位进行操作的方式。Python 提供了多种位运算符,例如:

  • &(按位与):两个对应位都为 1 时结果为 1。
  • |(按位或):任一对应位为 1 时结果为 1。
  • ~(按位非):将每一位取反。
  • ^(按位异或):对应位不同则为 1,相同则为 0。

如何用位运算管理权限?

每个权限对应一个独立的二进制位,下面的例子中设置了ABCD四种权限:

  • 权限 A:0001(十进制 1)
  • 权限 B:0010(十进制 2)
  • 权限 C:0100(十进制 4)
  • 权限 D:1000(十进制 8)

每一个权限都是独立的一位,多种权限可以组合为一个整数。例如:

  • 3 表示拥有权限 A 和 B,因为 0011 的二进制表示第 0 位和第 1 位为 1

这种方法可以在复杂权限的情况下极大程度节约内存空间,以及逻辑复杂度。

示例代码

以下是实现权限管理的 Python 示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 定义权限常量
PERMISSION_A = 1  # 0001
PERMISSION_B = 2  # 0010
PERMISSION_C = 4  # 0100
PERMISSION_D = 8  # 1000

# 当前权限状态
permissions = 0  # 初始状态无权限

# 赋予权限
def add_permission(current, permission):
    return current | permission

# 移除权限
def remove_permission(current, permission):
    return current & ~permission

# 检查是否拥有某个权限
def has_permission(current, permission):
    return (current & permission) != 0

  1. 添加权限 A 和 B:
1
2
3
4
5
6
7
8
9
10
11
12
permissions = add_permission(permissions, PERMISSION_A)  # 添加权限 A
permissions = add_permission(permissions, PERMISSION_B)  # 添加权限 B
print(f"当前权限: {bin(permissions)}")  # 输出二进制表示

if has_permission(permissions, PERMISSION_A):
    print("拥有权限 A")
else:
    print("没有权限 A")


当前权限: 0b11
拥有权限 A
  1. 移除权限 A:
1
2
3
4
5
6
7
8
9
permissions = remove_permission(permissions, PERMISSION_A)  # 移除权限 A
print(f"移除权限 A 后: {bin(permissions)}")
if has_permission(permissions, PERMISSION_A):
    print("拥有权限 A")
else:
    print("没有权限 A")

移除权限 A : 0b10
没有权限 A

原理解析

赋予权限

通过按位或 | 操作,将对应权限位设置为 1。例如:

1
2
3
current = 0b0010
permission = 0b0001
new_permissions = current | permission  # 结果为 0b0011

移除权限

通过按位非 ~ 和按位与 &,将对应权限位设置为 0。例如:

1
2
3
current = 0b0011
permission = 0b0001
new_permissions = current & ~permission  # 结果为 0b0010

检查权限

通过按位与 & 操作检测某位是否为 1

1
2
3
current = 0b0011
permission = 0b0001
has_permission = (current & permission) != 0  # 结果为 True