面试题答案
一键面试1. 设计思路
- 元类:元类用于创建类,在这里我们通过元类来扫描类的方法,并检查是否有特定的权限装饰器。如果有,将权限信息存储起来,以便后续在方法调用时进行权限验证。
- 装饰器:装饰器用于标记类方法,并指定调用该方法所需的权限。
2. 代码实现
# 定义权限装饰器
def require_permission(permission):
def decorator(func):
func.required_permission = permission
return func
return decorator
# 定义元类
class PermissionMeta(type):
def __new__(cls, name, bases, attrs):
new_attrs = {}
for attr_name, attr_value in attrs.items():
if callable(attr_value) and hasattr(attr_value, 'required_permission'):
def wrapper(self, *args, **kwargs):
if hasattr(self, 'has_permission') and self.has_permission(attr_value.required_permission):
return attr_value(self, *args, **kwargs)
else:
raise PermissionError(f"User does not have permission: {attr_value.required_permission}")
new_attrs[attr_name] = wrapper
else:
new_attrs[attr_name] = attr_value
return super().__new__(cls, name, bases, new_attrs)
# 使用元类和装饰器
class User:
__metaclass__ = PermissionMeta
def __init__(self, permissions):
self.permissions = permissions
def has_permission(self, permission):
return permission in self.permissions
@require_permission('admin')
def admin_method(self):
print("This is an admin - only method.")
# 测试代码
admin_user = User(['admin'])
admin_user.admin_method()
regular_user = User(['user'])
try:
regular_user.admin_method()
except PermissionError as e:
print(e)
3. 代码解释
- 权限装饰器
require_permission
:- 这是一个高阶函数,接受一个
permission
参数。 - 它返回一个内部装饰器
decorator
,这个内部装饰器接受一个函数func
作为参数。 - 在
decorator
函数内部,为func
添加了一个required_permission
属性,值为传入的permission
,然后返回func
。这样就标记了该方法所需的权限。
- 这是一个高阶函数,接受一个
- 元类
PermissionMeta
:- 在
__new__
方法中,遍历类的属性。 - 如果属性是可调用的(即方法)且具有
required_permission
属性(说明该方法被权限装饰器标记了),则创建一个新的包装函数wrapper
。 - 在
wrapper
函数中,首先检查实例是否有has_permission
方法,并且当前用户是否具有调用该方法所需的权限。如果有则调用原始方法,否则抛出PermissionError
。 - 最后,使用
super().__new__
创建并返回新的类。
- 在
User
类:- 使用
__metaclass__ = PermissionMeta
指定使用PermissionMeta
作为元类。 - 构造函数
__init__
接受用户的权限列表并存储。 has_permission
方法用于检查用户是否具有特定权限。admin_method
方法被@require_permission('admin')
装饰,标记该方法需要admin
权限才能调用。
- 使用
通过这种方式,元类和装饰器协同工作,实现了类方法的权限控制。