7. 装饰器的嵌套装饰

目标

使用装饰器,对银行存钱(savemoney)和取钱(withdraw)业务的实际操作函数成功调用后模拟发送短信息。

对一个函数可以添加多个装饰器。

装饰器的嵌套装饰的语法

@装饰器n <换行>
...
@装饰器2 <换行>
@装饰器1 <换行>
def 被装饰函数名(形参列表):
    语句块

说明

上述语法等价于

@装饰器n <换行>
...
@装饰器2 <换行>
@装饰器1 <换行>
def 被装饰函数名(形参列表):
    语句块

# 等价于 
被装饰函数名 = 装饰器2(装饰器1(被装饰函数名))

示例

# 此示例示意 装饰器的嵌套装饰 的用法

bank_account = {
    '魏明择': {'password': '123456', 'money': 500},
    '小张': {'password': '654321', 'money': 10000},
}

def message_send(fn):
    def wrap(name, x):
        r = fn(name, x)
        print(name, '您办理了银行的业务,短息发送中...')
        return r
    return wrap

def privileged_check(fn):
    '权限管理装饰器'
    def wrap(name, x):
        if name not in bank_account:
            raise ValueError(f'账户异常')
        password = input(f'请输入{name}的密码: ')
        if password != bank_account[name]['password']:
            raise ValueError(f'账户异常')
        return fn(name, x)
    return wrap


@message_send
@privileged_check
def savemoney(name, x):  # 存钱
    bank_account[name]['money'] += x
    print(name, "存钱", x, "元。")

@privileged_check
def withdraw(name, x):  # 取钱
    bank_account[name]['money'] -= x
    print(name, "取钱", x, "元。")

print('原来的银行账户:', bank_account)
savemoney("魏明择", 200)
savemoney("小张", 20000)
withdraw("魏明择", 300)
print('现在的银行账户:', bank_account)

上述程序实现了对savemoney 添加了 权限管理的装饰器 privileged_check 后,又添加了 message_send装饰器。