python-学习 初级atm小脚本、函数嵌套、装饰器、生成器、迭代器、三元表达式
一、作业需求:
模拟实现一个ATM + 购物商城程序
1.额度 15000或自定义
2.实现购物商城,买东西加入 购物车,调用信用卡接口结账
3.可以提现,手续费5%
4.每月22号出账单,每月10号为还款日,过期未还,按欠款总额 万分之5 每日计息
5.支持多账户登录
6.支持账户间转账
7.记录每月日常消费流水
8.提供还款接口
9.ATM记录操作日志
10.提供管理接口,包括添加账户、用户额度,冻结账户等。。。
11.用户认证用装饰器
要求1、2、3、6、8、9、11以实现 要求4、5、7、10、未实现
登录ID:1234 密码:abc123
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import time 2 current_user={'id':None} 3 wenjian=open('db.txt','r+',encoding='utf-8') 4 duqu=eval(wenjian.readline()) 5 shijian=time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time())) #定义日志操作时间 6 def log(rizhi): 7 with open('log.txt','a',encoding='utf-8') as l: 8 l.write(rizhi) 9 return rizhi 10 def renzheng(zhanghu): 11 def auth(): 12 while True: 13 if current_user['id']: 14 return zhanghu() 15 name_id=input('请输入银行卡ID: ').strip() 16 password=input('请输入密码: ') .strip() 17 if len(password)== 0 and len(name_id) ==0 : 18 print('错误❌') 19 if name_id == duqu['id'] and password == duqu['password'] : 20 print('登录成功') 21 current_user['id']=name_id 22 log('%s 账户[%s]登录成功\n' % (shijian, name_id)) #记录登录日志 23 return zhanghu() 24 else: 25 print('登录失败,请检查账户名或密码') 26 log('%s 账户[%s]登录失败\n'%(shijian,name_id)) 27 return auth 28 @renzheng 29 def chaxun(): 30 edu = duqu['money'] 31 xiaofei = duqu['shengyu'] 32 if xiaofei > edu: 33 huankuan = 0 34 else: 35 huankuan = edu - xiaofei 36 print(''' 37 总信用额度:%s 38 剩余可消费:%s 39 本月应还款:%s 40 ''' % (edu, xiaofei, huankuan)) 41 time.sleep(3) 42 @renzheng 43 def huankuan(): 44 huankuan = input('请输入还款金额:').strip() 45 if huankuan.isdigit(): 46 xiaofei = duqu['shengyu'] 47 xiaofei += int(huankuan) 48 duqu['shengyu'] = xiaofei 49 print('还款中,请稍后..........') 50 time.sleep(2) 51 print('还款成功,账户可消费金额:%s' % xiaofei) 52 time.sleep(3) 53 wenjian = open('db.txt', 'w', encoding='utf-8') 54 wenjian.write(str(duqu)) 55 wenjian.close() 56 @renzheng 57 def gouwuche(): #以前的作业拿来改吧改吧就用上了 58 goods = [ 59 {"name": "电脑", "price": 1999}, 60 {"name": "鼠标", "price": 10}, 61 {"name": "游艇", "price": 20}, 62 {"name": "娃娃", "price": 3998}, 63 {"name": "气筒", "price": 99}, 64 ] 65 kong = [] 66 qian = [] 67 while True: 68 for k, v in enumerate(goods): 69 print(k, '商品: {name} 价格: {price} RMB'.format(price=v['price'], name=v['name'])) 70 sp = input('请输入购买的商品编号[输入j结账][输入r删除购物车商品][输入q退出]: ').strip() 71 if sp == 'q' and len(sp) != 0: 72 break 73 elif sp == 'r': 74 while True: 75 if kong == []: 76 print('======================》没有商品可删了《=====================') 77 break 78 print('您以购买的商品: ') 79 for k, v in enumerate(kong): # for循环显示已购买的商品 80 print(k, '商品: {name} 价格: {price} RMB'.format(price=v[1], name=v[0])) 81 sc = input('请输入删除的商品编号[输入q返回]: ').strip() 82 if sc == 'q' and len(sc) != 0: 83 break 84 if sc.isdigit(): 85 if int(sc) < len(kong) and int(sc) >= 0: # 判断输入的数字不能大于列表的下标数字和小于0 86 kong.remove(kong[int(sc)]) # 删除购物车商品 87 else: 88 print('!!!!!!!!!!!!!!!!无效的输入!!!!!!!!!!!!!!!!!!!') 89 else: 90 print('\033[42m请输入要删除的商品编号哦~\033[0m') 91 elif sp.isdigit(): 92 if int(sp) < len(goods) and int(sp) >= 0: 93 jiaqian = goods[int(sp)]['price'] 94 mingzi = goods[int(sp)]['name'] 95 kong.append((mingzi, jiaqian)) 96 qian.append(jiaqian, ) 97 print('\033[42m您以购买的商品:[ %s ] 价钱RMB:[ %s ]\033[0m' % (mingzi, jiaqian)) 98 else: 99 print('>>>>>>>>>>>>>>>>>不要瞎搞!!!按提示操作!!!不要瞎搞!!!<<<<<<<<<<<<<<<<<<<<<') 100 elif sp == 'j': 101 while True: 102 res = sum(i for i in qian) 103 print('您总共消费了:%s' % res) 104 m = input('是否跳转到ATM结账y或n: ').strip() 105 if len(m)==0: 106 print('按提示操作!!') 107 continue 108 elif m == 'y': 109 jiezhang=duqu['shengyu'] 110 print(' 正在跳转请稍后.........') 111 time.sleep(3) 112 if jiezhang <= 0: 113 print('您的余额不足!!!!!') 114 jiezhang-=res 115 time.sleep(1) 116 print('支付成功,卡内剩余可消费金额:%s。'%jiezhang) 117 duqu['shengyu']=jiezhang 118 wenjian=open('db.txt','w',encoding='utf-8') 119 wenjian.write(str(duqu)) #将剩余金额写进文件里 120 wenjian.close() 121 print('正在返回商品页面,请稍后..........') 122 time.sleep(3) 123 break 124 elif m =='n': 125 break 126 else:continue 127 else: 128 print('>>>>>>>>>>>>>>>>>不要瞎搞!!!按提示操作!!!不要瞎搞!!!<<<<<<<<<<<<<<<<<<<<<') 129 @renzheng 130 def zhiqian(): 131 while True: 132 quxian = input('请输入取现金额(输入b返回): ').strip() 133 shengyu = duqu['shengyu'] 134 if len(quxian) == 0: 135 print('!!!!!非法字符!!!!!') 136 continue 137 elif quxian == 'b': 138 break 139 elif quxian.isalpha(): 140 print('!!!!!非法字符!!!!') 141 continue 142 elif shengyu <= 0 or int(quxian) > shengyu: 143 print('您的余额不足!!!!!') 144 continue 145 elif quxian is float: 146 print('请输入整数') 147 elif quxian.isdigit(): 148 quxian=int(quxian) 149 shouxufei=quxian*0.05 150 shengyu=shengyu-quxian-shouxufei 151 print('%s 成功取现:%s 账户剩余:%s 手续费:%s' % (shijian, quxian, shengyu,shouxufei)) 152 log('%s 成功取现:%s 账户剩余:%s 手续费:%s\n' % (shijian, quxian, shengyu,shouxufei)) #记录取钱日志 153 duqu['shengyu'] = shengyu 154 wenjian = open('db.txt', 'w', encoding='utf-8') 155 wenjian.write(str(duqu)) 156 wenjian.close() 157 continue 158 else: 159 print('输入错误!!!!!') 160 continue 161 162 163 164 @renzheng 165 def caidan(): 166 while True: 167 print('======================================================================================') 168 print(''' 169 1.查询余额 170 2. 转账 171 3. 取现 172 4. 购物 173 5. 还款 174 6.操作日志 175 7.退 出 176 ''') 177 print('======================================================================================') 178 xuanze=input('请输入您要操作的选项:').strip() 179 if xuanze == '1':chaxun() 180 elif xuanze == '2':print('-------------------该功能未实现---------------------') 181 elif xuanze == '3':zhiqian() 182 elif xuanze == '4':gouwuche() 183 elif xuanze == '5': 184 chaxun() 185 huankuan() 186 elif xuanze == '6': 187 with open('log.txt',encoding='utf-8') as log_f: 188 for i in log_f: 189 print(i) 190 time.sleep(3) 191 elif xuanze == '7':break 192 else: 193 print('按提示操作!!') 194 time.sleep(2) 195 continue 196 197 caidan()
二、笔记
1.函数嵌套
函数的嵌套定义:在一个函数的内部,又定义另外一个函数
函数的嵌套调用:在调用一个函数的过程中,又调用了其他函数
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 def bar(): 2 print('from nbar') 3 4 def foo(): 5 print('from foo') 6 bar() 7 8 foo()
2.装饰器
1 开放封闭原则:对扩展是开放的,对修改是封闭
2 装饰器:装饰它人的工具,装饰器本身可以是任意可调用对象,被装饰的对象本身也可以是任意可调用对象
2.1 装饰器的遵循的原则:1 不修改被装饰对象的源代码 2 不修改被调用对象的调用方式
2.2 装饰器的目的是:在遵循1和2原则的前提,为其他新功能函数添加
3 @装饰器名,必须写在被装饰对象的正上方,并且是单独一行
4 一个函数头顶上可以多个装饰器(最先执行的是第一个)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import time 2 3 def timmer(func): 4 # func=index 5 def wrapper(): 6 start=time.time() 7 func() 8 stop=time.time() 9 print('run time is %s' %(stop-start)) 10 return wrapper 11 12 13 @timmer # index=timmer(index) 14 def index(): 15 time.sleep(3) 16 print('welcome to index') 17 @timmer # home=timmer(home) 18 def home(): 19 time.sleep(2) 20 print('welcome to home page') 21 22 index() 23 home()
2.1 无参装饰器版本
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 current_user={'user':None} 2 def auth(func): 3 def wrapper(*args,**kwargs): 4 if current_user['user']: 5 return func(*args,**kwargs) 6 7 name=input('name: ').strip() 8 password=input('password: ').strip() 9 10 with open('db.txt', encoding='utf-8') as f: 11 user_dic = eval(f.read()) 12 if name in user_dic and password == user_dic[name]: 13 res=func(*args,**kwargs) 14 current_user['user']=name 15 return res 16 else: 17 print('user or password error') 18 return wrapper 19 20 @auth #index=auth(index) index=wrapper 21 def index(): 22 print('from index') 23 index() 24 25 @auth 26 def home(name): 27 print('welcome %s' %name) 28 29 index() #wrapper() 30 home('egon')
2.2. 有参装饰器版本
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 current_user={'user':None} 2 def auth(auth_type='file'): 3 def deco(func): 4 def wrapper(*args, **kwargs): 5 if auth_type == 'file': 6 if current_user['user']: 7 return func(*args, **kwargs) 8 name = input('name: ').strip() 9 password = input('password: ').strip() 10 11 with open('db.txt', encoding='utf-8') as f: 12 user_dic = eval(f.read()) 13 if name in user_dic and password == user_dic[name]: 14 res = func(*args, **kwargs) 15 current_user['user'] = name 16 return res 17 else: 18 print('user or password error') 19 elif auth_type == 'mysql': 20 print('mysql') 21 22 elif auth_type == 'ldap': 23 print('ldap') 24 else: 25 print('not valid auth_type') 26 return wrapper 27 return deco 28 29 30 31 32 33 34 @auth(auth_type='mysql') #@deco #index=deco(index) 35 def index(): 36 print('from index') 37 @auth(auth_type='file') 38 def home(name): 39 print('welcome %s' %name) 40 index() #wrapper() 41 home('egon')
3.列表解析
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 l=[] 2 for i in range(10): 3 if i >=5: 4 l.append('egg%s' %i) 5 6 print(l) 7 8 列表解析 9 for i0 in ...: 10 if 条件1: 11 for i1 in ...: 12 if 条件2: 13 for i2 in ...: 14 if 条件3: 15 。。。 16 17 l=['egg%s' %i for i in range(10) if i >=5] 18 print(l) 19 20 nums=[1,2,3,4,5,6] 21 nums_new=[item**2 for item in nums if item > 3] 22 print(nums_new) 23 24 25 nums_new=[] 26 for item in nums: 27 nums_new.append(item**2) 28 29 print(nums_new) 30 31 32 names=['alex_sb','wupeiqi_sb','egon','yuanhao_sb'] 33 34 names_new=[name for name in names if name.endswith('sb')] 35 print(names_new)
4.生成器
1.生成器表达式
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 # g=('egg%s' %i for i in range(1000)) 2 # print(g) 3 # print(next(g)) 4 # print(next(g)) 5 # print(next(g)) 6 7 8 9 # with open('a.txt',encoding='utf-8') as f: 10 # # res=max((len(line) for line in f)) 11 # res=max(len(line) for line in f) 12 # print(res) 13 14 # print(max([1,2,3,4,5,6])) 15 16 17 # with open('a.txt',encoding='utf-8') as f: 18 # g=(len(line) for line in f) 19 # print(max(g)) 20 # print(max(g)) 21 # print(max(g))
1.生成器:在函数内部包含yield关键,那么该函数执行的结果是生成器
2.生成器就是迭代器
3.yield的功能:
4. 把函数的结果做生迭代器(以一种优雅的方式封装好__iter__,__next__)
5. 函数暂停与再继续运行的状态是由yield
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 # def func(): 2 # print('first') 3 # yield 11111111 4 # print('second') 5 # yield 2222222 6 # print('third') 7 # yield 33333333 8 # print('fourth') 9 # 10 # 11 # g=func() 12 # print(g) 13 # from collections import Iterator 14 # print(isinstance(g,Iterator)) 15 16 # print(next(g)) 17 # print('======>') 18 # print(next(g)) 19 # print('======>') 20 # print(next(g)) 21 # print('======>') 22 # print(next(g)) 23 24 # for i in g: #i=iter(g) 25 # print(i) 26 27 28 29 30 # def func(n): 31 # print('我开动啦') 32 # while True: 33 # yield n 34 # n+=1 35 # 36 # g=func(0) 37 # 38 # print(next(g)) 39 # print(next(g)) 40 # print(next(g)) 41 # for i in g: 42 # print(i) 43 44 45 46 47 48 # 49 # for i in range(10000): 50 # print(i) 51 52 # def my_range(start,stop): 53 # while True: 54 # if start == stop: 55 # raise StopIteration 56 # yield start #2 57 # start+=1 #3 58 # 59 # g=my_range(1,3) 60 # 61 # print(next(g)) 62 # print(next(g)) 63 # print(next(g)) 64 # 65 66 # 67 # for i in my_range(1,3): 68 # print(i)
yield与return的比较?
相同:都有返回值的功能
不同:return只能返回一次值,而yield可以返回多次值
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 # python3 tail.py -f access.log | grep 'error' 2 import time 3 4 def tail(filepath): 5 with open(filepath, 'r') as f: 6 f.seek(0, 2) 7 while True: 8 line = f.readline() 9 if line: 10 yield line 11 else: 12 time.sleep(0.2) 13 14 15 def grep(pattern,lines): 16 for line in lines: 17 if pattern in line: 18 print(line,end='') 19 20 grep('error',tail('access.log'))
5.三元表达式
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 # def foo(x): 2 # if x > 3: 3 # return 'ok' 4 # else: 5 # return 'no' 6 # 7 # x=10 8 # res=x if x > 3 else 'no' 9 # print(res) 10 11 12 # def max2(x,y): 13 # return x if x > y else y 14 # print(max2(1,3)) 15 16 17 # name='egon' 18 # print('SB' if name == 'alex' else 'shuai')
6.迭代器
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #迭代:是一个重复的过程,每一次重复,都是基于上一次的结果而来 2 # while True: #单纯的重复 3 # print('你瞅啥') 4 5 # l=['a','b','c','d'] 6 # count=0 7 # while count < len(l): 8 # print(l[count]) 9 # count+=1 10 11 dic={'name':'egon','sex':'m',"age":18} #上述按照索引的取值方式,不适于没有索引的数据类型 12 13 #迭代器: 14 #可迭代对象iterable:凡是对象下有__iter__方法:对象.__iter__,该对象就是可迭代对象 15 # s='hello' 16 # l=['a','b','c','d'] 17 # t=('a','b','c','d') 18 # dic={'name':'egon','sex':'m',"age":18} 19 # set1={1,2,3} 20 # f=open('db.txt') 21 22 # s.__iter__() 23 # l.__iter__() 24 # t.__iter__() 25 # dic.__iter__() 26 # set1.__iter__() 27 # f.__iter__() 28 29 30 #迭代器对象:可迭代对象执行内置的__iter__方法,得到的结果就是迭代器对象 31 32 # dic={'name':'egon','sex':'m',"age":18} 33 # 34 # i=dic.__iter__() 35 # # print(i) #iterator迭代器 36 # 37 # # i.__next__() #next(i) 38 # print(next(i)) 39 # print(next(i)) 40 # print(next(i)) 41 # print(next(i)) #StopIteration 42 # 43 # l=['a','b','c','d'] 44 # 45 # i=l.__iter__() 46 # print(next(i)) 47 # print(next(i)) 48 # print(next(i)) 49 # print(next(i)) 50 # print(next(i)) #StopIteration 51 52 53 54 55 #不依赖于索引的取值方式 56 # l=['a','b','c','d'] 57 # dic={'name':'egon','sex':'m',"age":18} 58 # iter_l=iter(l) 59 # iter_dic=iter(dic) 60 # while True: 61 # try: 62 # # print(next(iter_l)) 63 # k=next(iter_dic) 64 # print(k,dic[k]) 65 # except StopIteration: 66 # break 67 68 69 #什么是迭代器对象: 70 #1 有__iter__,执行得到仍然是迭代本身 71 #2 有__next__ 72 73 74 #迭代器对象的优点 75 #1:提供了一种统一的(不依赖于索引的)迭代方式 76 #2:迭代器本身,比起其他数据类型更省内存 77 # l=['a','b','c','d'] 78 # i=iter(l) 79 80 # dic={'a':1,'b':2} 81 # x=dic.keys() 82 # print(x) 83 # i=x.__iter__() 84 # 85 # with open('a.txt') as f: 86 # # print(next(f)) 87 # # print(next(f)) 88 # # print(next(f)) 89 # f.read() 90 91 92 #迭代器对象的缺点 93 #1:一次性,只能往后走,不能回退,不如索引取值灵活 94 #2:无法预知什么时候取值结束,即无法预知长度 95 # l=['a','b','c','d'] 96 # i=iter(l) 97 # print(next(i)) 98 # print(next(i)) 99 # print(next(i)) 100 101 102 #for循环原理 103 104 # 105 # l=['a','b','c','d'] 106 # for item in l: #iter_l=l.__iter__() 107 # print(item) 108 109 110 # for item in {1,2,3,4}: 111 # print(item) 112 113 114 # with open('a.txt') as f: 115 # # for line in f: #i=f.__iter__() 116 # # print(line) 117 # print(f is f.__iter__()) 118 119 120 121 122 123 #补充:判断可迭代对象与迭代器对象(了解) 124 125 from collections import Iterable,Iterator 126 s='hello' 127 l=['a','b','c','d'] 128 t=('a','b','c','d') 129 dic={'name':'egon','sex':'m',"age":18} 130 set1={1,2,3} 131 f=open('a.txt') 132 133 134 # print(isinstance(s,Iterable)) 135 # print(isinstance(l,Iterable)) 136 # print(isinstance(t,Iterable)) 137 # print(isinstance(dic,Iterable)) 138 # print(isinstance(set1,Iterable)) 139 # print(isinstance(f,Iterable)) 140 141 print(isinstance(s,Iterator)) 142 print(isinstance(l,Iterator)) 143 print(isinstance(t,Iterator)) 144 print(isinstance(dic,Iterator)) 145 print(isinstance(set1,Iterator)) 146 print(isinstance(f,Iterator))