python - 装饰器导致所有函数返回 True
问题描述
为了调试我遇到问题的在线权限系统,我创建了几个类和函数,旨在离线复制问题。不幸的是,我遇到了一个问题,将一个函数变成一个装饰器会完全改变一个装饰函数的结果。
我的代码如下,我尽可能保持基本,以说明我的观点。
设置用户类:
class User(object): def __init__(self, forename=None, surname=None, logged_in=True, exists=True, poop=False, admin=False): self.forename = forename self.surname = surname self.logged_in = logged_in self.exists = exists self.poop = poop self.admin = admin def __repr__(self): return f'User: {self.forename} {self.surname}.' user1 = User('Paddy', 'McHugh', True, True, False, True) user2 = User('Rodney', 'Donger', False, False, True, False) user3 = User('Bob', 'Dangler', True, True, True, True)
创建函数以针对用户进行测试:
def user_just_is(user): return user.exists def user_is_poop(user): return user.poop def user_is_admin(user): return user.admin
使用常规功能针对所选用户测试这些功能:
class Permissions2(object): def __init__(self): pass def requires(self, *args): user = user2 if not user.logged_in: print('You\'re not logged in, please log in.') return if not all(i(user) for i in args): print('Not all of the conditions were met.') else: print('All of the conditions were met.') Permissions2().requires(user_just_is, user_is_poop, user_is_admin)
使用装饰器功能针对所选用户测试这些功能:
class Permissions(object): def __init__(self): pass def requires(self, *args): user = user2 def decorator(func): @wraps(func) def allower(*args, **kwargs): if not user.logged_in: print('You\'re not logged in, please log in.') return if not all(i(user) for i in args): print('Not all of the conditions were met.') return return func(*args, **kwargs) return allower return decorator @Permissions.requires(user_just_is, user_is_poop, user_is_admin) def print_stuff(): print('All of the conditions were met.') print_stuff()
我希望常规函数和装饰器函数的结果是相同的。如果 User.logged_in == False,那么它将打印:'You're not logged in, please log in.'
。如果所有布尔变量都是 True,它将打印:'All of the conditions were met.'
。如果任何条件为 False,它将打印:'Not all of the conditions were met.'
。
装饰器函数仍然返回'You're not logged in, please log in'
,但如果 User.logged_if == True ,那么其他布尔值无关紧要,它总是返回 True 给all()
函数和 print 'All of the conditions were met.'
。
将它放在装饰器中意味着all()
似乎对所有测试的函数都返回 True 是什么意思?
解决方案
args
您的allower
函数的参数会隐藏 的参数args
,requires
因此当您在此处迭代时args
:
if not all(i(user) for i in args):
您不再遍历传递给requires
as的函数列表args
,而是args
传递给装饰函数。您应该重命名参数以避免命名冲突。
此外,您将定义Permissions.requires
为实例方法,因此它的第一个参数是self
,该方法绑定到的对象,因此当您调用时:
@Permissions.requires(user_just_is, user_is_poop, user_is_admin)
user_just_is
作为 传递self
,而不是成为 的一部分args
。由于requires
实际上并未使用self
,因此应将其定义为静态方法。
因此,修复了上述问题后,您的Permissions
课程应如下所示:
class Permissions(object):
@staticmethod
def requires(*conditions):
user = user2
def decorator(func):
@wraps(func)
def allower(*args, **kwargs):
if not user.logged_in:
return print('You\'re not logged in, please log in.')
if not all(i(user) for i in conditions):
return print('Not all of the conditions were met.')
return func(*args, **kwargs)
return allower
return decorator
推荐阅读
- firebase-realtime-database - Dart Null Coalescing 不返回默认值
- c# - 无法从抽象 System.Drawing.Image 类派生类
- r - 如何在 R 中使用“显示更多”属性从网站上抓取文本?
- c# - 在 C# try-finally 中如何捕获原始异常
- java - 从 String 的 getchars() 方法创建的 char 数组的最后一个字符更改为不同的字符
- php - Laravel 注册失败且没有错误
- c - 不带参数调用 exit()
- c# - 从多个局部视图收集用户输入数据
- xcode - 如何在将应用程序上传到 App Store 时修复错误“找不到主包”
- python - 尝试在自定义 LearnerCallback 中应用_tfms 时如何修复“后端 CUDA 的预期对象”