协程和装饰器完成简易计算器
1 import functools as ft 2 import itertools as it 3 4 OPERATORS='+','-','/','*' 5 EXIT_COMMANDS='exit','quit' 6 7 #验证最近输入的三个数是否能构成计算公式 8 def can_calculate(state): 9 if len(state)<3: 10 return False 11 *_,i1,op,i2=state #unpack state并从倒数开始赋值,list的倒数第一个赋值给i2,倒数第二个赋值给op,倒数第三个赋值给i1,剩下的赋值给*_ 12 return isinstance(i1,float) and op in OPERATORS and isinstance(i2,float) 13 14 #计算 15 def calculate(state): 16 *_,i1,op,i2=state 17 if op=='+': 18 result=i1+i2 19 elif op=='-': 20 result=i1-i2 21 elif op=='/': 22 result=i1/i2 23 elif op=='*': 24 result=i1*i2 25 else: 26 raise ValueError('Invalid operator!') 27 print('%f %s %f=%f'%(i1,op,i2,result)) 28 return result 29 30 #验证输入是否合法 31 def validate_input(fnc): 32 def inner(): 33 i=fnc() #i=get_input()=input() 34 try: 35 i=float(i) 36 except ValueError: 37 pass 38 if isinstance(i,float) or i in OPERATORS or i in EXIT_COMMANDS: 39 return i 40 return None 41 42 return inner 43 44 #通过装饰器验证合法输入并返回 45 @validate_input 46 def get_input(): #get_input=validate_input(get_input) i=get_input()=inner() 47 return input() 48 49 def process_input(): 50 state=[] 51 while True: 52 update=yield 53 state.append(update) #state=[1,*,3,+,4] 54 if can_calculate(state): 55 result=calculate(state) 56 state.append(result) #state=[1,*,3,3,7] 57 58 59 #获取输入计算器的值并将值发送给process_input()函数 60 def calculator(): 61 g=process_input() 62 g.send(None) 63 while True: #i=get_input()=inner() 64 i=get_input() #如果输入的值为非数字或则操作符验证器将返回None 65 if i is None: 66 print('Please enter a number or an operator') 67 continue 68 if i in EXIT_COMMANDS: 69 break 70 g.send(i) 71 72 calculator()
运行结果如下
1 3 2 * 3 5 4 3.000000 * 5.000000=15.000000 5 - 6 1 7 15.000000 - 1.000000=14.000000 8 / 9 3 10 14.000000 / 3.000000=4.666667 11 * 12 5 13 4.666667 * 5.000000=23.333333 14 * 15 6 16 23.333333 * 6.000000=140.000000 17 / 18 22 19 140.000000 / 22.000000=6.363636 20 exit