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