python - 装饰器导致所有函数返回 True

标签 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,那么它将打印:'您尚未登录,请登录。'。如果所有 bool 变量都为 True,则会打印:'所有条件均得到满足。'。如果任何条件为 False,则会打印:'并非所有条件均得到满足。'

装饰器函数仍然返回'您尚未登录,请登录',但如果 User.logged_if == True,那么其他 bool 值并不重要,它总是返回符合 all() 函数并打印 'All of the criteria were met.'

将其放入装饰器中意味着 all() 似乎对所有测试的函数返回 True 是什么?

最佳答案

allower 函数的 args 参数会隐藏 requiresargs 参数,因此当您迭代时此处的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/

相关文章:

python - 更改 networkx 中的箭头类型

python - Pandas :按两列分组,将第一列组中的第一个值相加

python - 根据其他列中的值平均某些列

python - MATLABs填写PyPlot

python - Matplotlib:向 cartopy 图像添加颜色条

python - 如何将 numpy 矩阵边界设置为零?

python - 多个 python 装饰器检索原始函数

python - PyQt Python - 为 QPushButton 创建鼠标右键单击

python - 在Python中的正则表达式中使用变量

python - 对于 : not returning all lines 中的行