在尝试调试遇到问题的在线权限系统时,我创建了几个旨在离线复制问题的类和函数。不幸的是,我遇到了一个问题,将函数转变为装饰器会完全改变装饰函数的结果。
我的代码如下,我尽可能保持基本,以说明我的观点。
设置用户类别:
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,那么它将打印:'您尚未登录,请登录。'
。如果所有 bool 变量都为 True,则会打印:'所有条件均得到满足。'
。如果任何条件为 False,则会打印:'并非所有条件均得到满足。'
。
装饰器函数仍然返回'您尚未登录,请登录'
,但如果 User.logged_if == True,那么其他 bool 值并不重要,它总是返回符合 all()
函数并打印 'All of the criteria were met.'
。
将其放入装饰器中意味着 all()
似乎对所有测试的函数返回 True 是什么?
最佳答案
allower
函数的 args
参数会隐藏 requires
的 args
参数,因此当您迭代时此处的args:
if not all(i(user) for i in args):
您不再迭代作为 args
传递给 requires
的函数列表,而是将 args
传递给修饰函数。您应该重命名参数以避免命名冲突。
此外,您将 Permissions.requires 定义为实例方法,因此它的第一个参数是 self,即该方法绑定(bind)到的对象,因此当您调用:
@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
关于python - 装饰器导致所有函数返回 True,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55303870/