为了调试遇到问题的联机权限系统,我创建了两个类和函数来脱机复制问题。不幸的是,我遇到了一个问题,其中将一个函数转换为装饰器会完全改变一个装饰函数的结果。
我的代码如下,为了说明我的观点,我将其保持为基本。
设置用户类别:
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()
函数并打印{{1 }}。
将其放在装饰器中意味着'All of the conditions were met.'
似乎对所有经过测试的函数都返回True是什么?
答案 0 :(得分:2)
您的args
函数的allower
参数遮盖了args
的{{1}}参数,因此,当您在此处遍历requires
时:
args
您不再遍历作为if not all(i(user) for i in args):
传递给requires
的函数列表,而是遍历传递给修饰函数的args
。您应该重命名该参数以避免命名冲突。
此外,您将args
定义为实例方法,因此它的第一个参数是Permissions.requires
,该方法绑定到该对象,因此在调用时:
self
@Permissions.requires(user_just_is, user_is_poop, user_is_admin)
作为user_just_is
传递,而不是成为self
的一部分。由于args
实际上并未使用requires
,因此应将其定义为静态方法。
因此,解决了上述问题后,您的self
类应该如下所示:
Permissions