找到比例为2的组合几何序列号

Find the combination Geometric Sequence number in the ratio of 2

通过给定权限class,有没有更好的方法来附魔我的list_permission方法,我可以找到可用的权限

我尝试过的:

class Permission:
    READ = 1
    WRITE = 2
    EDIT = 4
    DELETE = 8

sum = 0
def has_permission(num, perm):
    """
    Return boolean for permission checking
    >>> has_permission(Permission.Read)
    assume sum = 6
    False
    """
    return num & perm == perm

def add_permission(num, perm):
    """
    sum permission number
    >>> add_permission(Permission.Read)
    sum + 1
    """
    return num += perm

def list_permission(num):
    pers = (per for per in dir(Permission) if not per.startswith("__"))
    lists = []
    for value in pers:
        if(has_permission(num, getattr(Permission, value))):
            lists.append(value)
    return lists


> print(list_permission(6))
> # [WRITE, EDIT]

一个小的优化可能是使用 Permission.__dict__ 而不是 dir(Permission)。阅读 this 了解 dir()__dir__ 之间的区别?

def list_permission(num):
    lists = []
    for key, val in Permission.__dict__.items():
        # Changed "__" to "_" in key.startswith.
        if not key.startswith("_") and has_permission(num, val):
            lists.append(key)
    return lists

如果你需要经常访问list_permission并且多用一些内存也无妨,那么做:

def list_permission(num, cache={}):
    if num in cache:
        return cache[num]

    permissions = []
    for key, val in Permission.__dict__.items():
        # Changed "__" to "_" in key.startswith.
        if not key.startswith("_") and has_permission(num, val):
            permissions.append(key)

    cache[num] = permissions

    return permissions

By given permission class, is there any better method to enchant my list_permission method that i can find out available permission

如果可以修改 Permission class,则按照 georg 在 中的建议使用 Enum

这是 Enum 的一个很好的用例:

from enum import Enum

class Permission(Enum):
    READ = 1
    WRITE = 2
    EDIT = 4
    DELETE = 8

然后

def list_permission(num):
    return [
        p.name
        for p in Permission
        if has_permission(num, p.value)
    ]

您要做的是 "interpret" 将一个数值放入其可能的权限集中,并将结果作为此类权限关键字的列表。

解决方案

因为您分配的值 (1, 2, 4, 8) 基本上是 (2**0, 2**1, 2**2, 2**3),这可以使用 decimal to binary 转换来建模。以下函数 get_permissions(pnum) 将为您提供所需的输出。

get_permissions(pnum = 7, permissions_dict = None)

输出

['READ', 'WRITE', 'EDIT']

处理边缘案例

当您提供的 pnum 大于最大允许值时,它还会处理边缘情况,在本例中为 15

get_permissions(pnum = 19, permissions_dict = None)

输出

WARNING::: MAX allowed value of pnum = 15
['READ', 'WRITE', 'EDIT', 'DELETE']

函数定义:get_permissions()

请注意,如果需要,您可以提供用户指定的 permissions_dict 来扩展此功能的范围。如果提供 permissions_dict,该函数将回退到其中定义的默认值。

permissions_dict = {'READ': 1, 'WRITE': 2, 'EDIT': 4, 'DELETE': 8}

def get_permissions(pnum = 0, permissions_dict = None):
    """
    Returns either a None for pnum=0,
    Or,
    a list of permission KEYWORDS.

    pnum = a non-negative integer
    permissions_dict: a dictionary specifying the permissions KEYWORDS
    >>>    If no permissions_dict is specified, it uses 
    >>>    a default permissions dictionary.
    """
    if permissions_dict is None:
        permissions_dict = {'READ': 1, 'WRITE': 2, 'EDIT': 4, 'DELETE': 8}
    # Max allowed value of pnum
    pnum_max = np.array(list(permissions_dict.values())).sum()
    if pnum==0:
        perm = None    
    else:
        if pnum>pnum_max:
            print("WARNING::: MAX allowed value of pnum = {}".format(pnum_max))
            pnum = pnum_max
        permissions = list(permissions_dict.keys())
        # Convert Decimal to Binary 
        #    ==> Convert to list of chars
        #        ==> Keep 4 chars: use str.zfill(4)
        #            ==> Flip Order 
        # Logic with Example: 
        # Dec(7) --> Bin(111) 
        #   ---> `0111` 
        #        ---> ['0','1','1','1'] 
        #            ---> ['1','1','1','0']
        p = list(str(int(bin(pnum)[2:])).zfill(4))
        p.reverse()
        # Extract permissions as KEYWORDS
        imax = len(permissions)
        perm = [permissions[i] for i,x in enumerate(p) if bool(int(x)) and i<imax]

    return perm

希望对您有所帮助。