如何使classmethod适配__getitem__?保留Permissions类__getitem__并优化as_list
解决方案
当然可以,这里有两种实用方案,既能保留__getitem__的实例调用能力,又能让as_list直接以Permissions.as_list()的形式调用,无需先实例化类。
方案一:抽取公共权限查找逻辑
核心思路是把__getitem__里的权限查找和异常抛出逻辑抽成一个类方法,让实例方法和类方法复用同一逻辑,避免代码重复。
修改后的完整代码:
from enum import Enum class Permission(Enum): CAN_DELETE = 'can_delete' CAN_EDIT = 'can_edit' class UserType(Enum): ADMIN = 'admin' GUEST = 'guest' PERMISSIONS = { UserType.ADMIN: [Permission.CAN_DELETE, Permission.CAN_EDIT], } class UnknownUserTypeError(Exception): pass class Permissions: permissions = PERMISSIONS @classmethod def _get_permissions(cls, user_type: UserType): try: return cls.permissions[user_type] except KeyError: raise UnknownUserTypeError def __getitem__(self, user_type: UserType): return self._get_permissions(user_type) @classmethod def as_list(cls, user_type: UserType): return [p.value for p in cls._get_permissions(user_type)] # 测试调用 try: perms = Permissions.as_list(UserType.GUEST) print(perms) except UnknownUserTypeError: print("未知用户类型") # 原有的实例下标访问依然可用 admin_perms_instance = Permissions()[UserType.ADMIN] print([p.value for p in admin_perms_instance])
说明
- 新增类方法
_get_permissions,封装了权限查找和异常处理的核心逻辑 - 实例方法
__getitem__调用这个类方法,保持原有的实例下标访问功能(比如Permissions()[UserType.ADMIN]依然有效) as_list直接调用_get_permissions,完全符合你想要的Permissions.as_list()API风格
方案二:实现类级别的__class_getitem__
如果你想额外让类本身支持下标操作(比如Permissions[UserType.ADMIN]),可以实现__class_getitem__特殊方法,这样as_list里就能直接用cls[user_type]了。
修改后的完整代码:
from enum import Enum class Permission(Enum): CAN_DELETE = 'can_delete' CAN_EDIT = 'can_edit' class UserType(Enum): ADMIN = 'admin' GUEST = 'guest' PERMISSIONS = { UserType.ADMIN: [Permission.CAN_DELETE, Permission.CAN_EDIT], } class UnknownUserTypeError(Exception): pass class Permissions: permissions = PERMISSIONS def __getitem__(self, user_type: UserType): try: return self.permissions[user_type] except KeyError: raise UnknownUserTypeError @classmethod def __class_getitem__(cls, user_type: UserType): try: return cls.permissions[user_type] except KeyError: raise UnknownUserTypeError @classmethod def as_list(cls, user_type: UserType): return [p.value for p in cls[user_type]] # 测试调用 try: perms = Permissions.as_list(UserType.GUEST) print(perms) except UnknownUserTypeError: print("未知用户类型") # 新增的类下标访问功能 admin_perms_class = Permissions[UserType.ADMIN] print([p.value for p in admin_perms_class]) # 原有的实例下标访问依然可用 admin_perms_instance = Permissions()[UserType.ADMIN] print([p.value for p in admin_perms_instance])
说明
__class_getitem__是Python 3.7+支持的特殊方法,专门用于实现类的下标操作- 此方案既保留了实例的
__getitem__功能,又新增了类级别的下标访问能力 as_list里直接使用cls[user_type],完全符合你的API偏好
方案选择
- 如果你只需要满足
Permissions.as_list()的调用需求,方案一更简洁,且避免了逻辑重复 - 如果你希望类本身也能像实例一样用下标访问权限,方案二更适合
内容的提问来源于stack exchange,提问作者barciewicz
相关产品推荐
相关产品推荐

