Python装饰器原理解析

Python的装饰器

装饰器是什么?

现在以Fibonacci Series为例子。对于如下代码,函数fib(n:int)可以返回从1开始的Fibonacci数列。

输出的结果便是fib(10)函数的迭代器,以及1~10的Fibonacci数列。

# Fibonacci Series
def fib(x:int):
    """Calculate the Fibonacci Series.
n starts from 1. If n=1 or n=2, yield 1. If n>2, yield fib(n-1)+fib(n-2).
"""
    a=1
    b=1
    for i in range(1,x+1):
        if i==1 or i==2:
            yield 1
        else:
            a,b=b,a+b
            yield b
# main function
def main():
    test=fib(10)
    print(test)
    for num in test:
        print(num,end=" ")

if __name__=="__main__":
    main()

运行结果:

>>> 
<generator object fib at 0x000000000410E630>
1 1 2 3 5 8 13 21 34 55

但是如果输入值小于等于0呢?运行的代码和结果如下:

# main function
def main():
    test=fib(-1)
    print(test)
    for num in test:
        print(num,end=" ")
# Result
>>> 
<generator object fib at 0x00000000043DE630>

既没有提示警告,也没有错误提示。如果这个函数被其它函数调用的话,完全不知道会出什么错误。

此时,装饰器便可以派上用处了。

from functools import wraps
# Decorator
def check_rule(func):
    """This is a decorator used to check:
- inputs are int
- inputs >=1
"""
    @wraps(func)
    def inner_wrapper(*args,**kwargs):
        # Loop the args
        for item in args:
            # Check int. If not, raise TypeError.
            if not isinstance(item,int):
                raise TypeError("You must input an integer.")
            # Check >=1. If not, raise ValueError.
            if item<1:
                raise ValueError("The input must larger or equal to 1.")
        return func(*args,**kwargs)
    return inner_wrapper

上面的代码是装饰器的实现代码。这个装饰器检查了:

  • 输入参数是不是int型
  • 输入的函数是不是大于等于1

之后,还需要对fib(n:int)函数进行修改,但是修改的内容很简单,只需要添加一句“语法糖”:

# fib function after decorator
@check_rule
def fib(x:int):
    """Calculate the Fibonacci Series.
n starts from 1. If n=1 or n=2, yield 1. If n>2, yield fib(n-1)+fib(n-2).
"""
    a=1
    b=1
    for i in range(1,x+1):
        if i==1 or i==2:
            yield 1
        else:
            a,b=b,a+b
            yield b

为了便于显示加了装饰器之后的结果,使用unittest模块。

import unittest
# Base class
# Input right number, negative number and float number
class TestFibFunction:
    """This class test the fib function with different inputs.
"""
    def test_fib(self):
        print() # Clear line
        #Print the args
        print("Input: ",self.arg)
        # Get the result
        x=fib(self.arg)
        # Print the result
        print("Result:")
        for i in x:
            print(i,end=" ")
        print() # Clear line
# Test right number
class TestNumber(TestFibFunction,unittest.TestCase):
    """This class test the right number.
"""
    arg=10
# Test negative number
class TestNegative(TestFibFunction,unittest.TestCase):
    """This class test the negtive number.
"""
    arg=-1
# Test float n
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值