装饰器使所有函数返回True

时间:2019-03-22 16:21:50

标签: python

为了调试遇到问题的联机权限系统,我创建了两个类和函数来脱机复制问题。不幸的是,我遇到了一个问题,其中将一个函数转换为装饰器会完全改变一个装饰函数的结果。

我的代码如下,为了说明我的观点,我将其保持为基本。

  1. 设置用户类别:

    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)
    
  2. 创建功能以对用户进行测试:

    def user_just_is(user):
        return user.exists
    
    
    def user_is_poop(user):
        return user.poop
    
    
    def user_is_admin(user):
        return user.admin
    
  3. 使用常规功能针对所选用户测试这些功能:

    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)
    
  4. 使用装饰器功能针对所选用户测试这些功能:

    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是什么?

1 个答案:

答案 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