需求
- 額度 15000或自定義
- 實現(xiàn)購物商城,買東西加入 購物車,調(diào)用信用卡接口結(jié)賬
- 可以提現(xiàn),手續(xù)費5%
- 支持多賬戶登錄
- 支持賬戶間轉(zhuǎn)賬
- 記錄每月日常消費流水
- 提供還款接口
- ATM記錄操作日志
- 提供管理接口,包括添加賬戶、用戶額度,凍結(jié)賬戶等。。。
- 用戶認證用裝飾器
需求分析
- 額度,初始化為15000,可以寫入一個文件里balance.txt
- 購物車應用,可以參考購物車作業(yè),整個購物車可以放到一個函數(shù)里,需要調(diào)用信用卡接口,就需要調(diào)用信用卡模塊了,購物車腳本可以和信用卡的放在一起
- 提現(xiàn),余額扣除提現(xiàn)金額*(1 + 0.05) 扣除金額不得大于余額的一半,提現(xiàn)完了之后扣除余額
- 多賬戶登陸,用戶名密碼寫入一個文件里,參考登陸接口作業(yè)
- 賬戶之間轉(zhuǎn)賬,用戶名對應的余額 - 轉(zhuǎn)賬金額,轉(zhuǎn)賬賬戶名對應的余額 + 轉(zhuǎn)賬金額
- 記錄流水,還需要寫一個流水文件,記錄消費商品,金額,前面還需要加時間
- 還款接口,可以理解為向余額添加
- ATM操作記錄
- 參考購物車作業(yè)里的
manage.py
- 裝飾器,我理解應該是不同的操作,給需要密碼驗證的,加上輸入密碼驗證模塊,就像真正的ATM那樣,非重要的操作可以不需要密碼
進一步思考:
balance和用戶密碼可以寫成字典形式,用pickle
導入到文件,到時候在load出來,方便處理,按用戶名,密碼,余額的形式對應起來,寫在一個文件里。
import pickle
info_dict={'root':{'userpasswd':'python','balance':10000},
'test':{'userpasswd':'test','balance':10000}}
f=open('user.info','wb')
pickle.dump(info_dict,f)
f.close()
購物車程序?qū)懺?code>shopplist.py里,功能有選擇商品,加入購物車,確認付款,到支付接口,完成后返回信息。
支付接口寫在credit.py
,支付函數(shù)payment()
,支付需要調(diào)用修改余額函數(shù)write_balance()
記錄賬單記錄函數(shù)consumer_logger()
提現(xiàn)接口也可以寫在credit.py
里,提現(xiàn)函數(shù)withdraw()
,提現(xiàn)需要調(diào)用修改余額函數(shù)write_balance()
,記錄操作記錄atm_logger()
賬戶間轉(zhuǎn)賬寫在credit.py
里,轉(zhuǎn)賬函數(shù)transfer()
,轉(zhuǎn)賬需要提供轉(zhuǎn)賬賬戶名,轉(zhuǎn)賬金額,需要調(diào)用修改余額函數(shù)write_balance()
,記錄操作記錄atm_logger()
還款接口也可以寫在credit.py
里,還款函數(shù)repay()
,需要調(diào)用修改余額函數(shù)write_balance()
,記錄操作記錄atm_logger()
結(jié)構:
我們先來確定程序的結(jié)構
-atm
--\bin
---atm.py
---shopping.py
---manager.py
--\core
---各類程序模塊
--\logs
---atm.log
---cust.log
其中bin目錄為執(zhí)行入口目錄,atm.py
是ATM仿真程序的啟動入口,shopping.py
是購物車程序的啟動入口,manager.py
是管理賬戶程序的啟動入口
core目錄下主要放置各類程序模塊
logs目錄下主要放置操作流水記錄日志,atm.log是ATM操作記錄,cust.log是信用卡消費記錄
setting目錄下主要放置配置文件
流程圖
我們先來確定atm的流程圖
然后是購物車的流程圖
最后是manager的流程圖
實現(xiàn)
用戶數(shù)據(jù)存放
考慮之前用字典存放用戶賬戶名和密碼,這次多了一個balance,那就字典里增加一個key叫'balance',字典形式這樣的:
{'test': {'balance': 11000.0, 'passwd': 'test'}, 'root': {'balance': 9000.0, 'passwd': 'python'}}
用戶名對應一個字典,內(nèi)字典key是passwd和balance,對應用戶的密碼和余額,在實現(xiàn)程序之前,先創(chuàng)建這個user.info
文件
我用pickle.dump
方法把測試用戶寫入文件:
import pickle
info_dict={'root':{'passwd':'python','balance':10000},
'test':{'passwd':'test','balance':10000}}
f=open('user.info','wb')
pickle.dump(info_dict,f)
f.close()
同樣的,用pickle
的方法,寫一個product.txt
的文件,用來存放商品信息,商品有名稱和價格,參考之前的購物車項目,我們做成列表類型。
寫product.txt
的腳本可以跟之前寫user.info
文件的腳本合并,做成一個初始化腳本:
import pickle
info_dict={'root':{'passwd':'python','balance':10000},
'test':{'passwd':'test','balance':10000}}
f=open('user.info','wb')
pickle.dump(info_dict,f)
f.close()
pro_list=[['iphone', 6200], ['mac pro', 12000], ['bike', 800], ['book', 55], ['coffee', 31], ['windows pc', 4900]]
f=open('product.txt','wb')
pickle.dump(pro_list,f)
f.close()
初始化數(shù)據(jù)好了之后,已經(jīng)擁有了一些測試賬號和商品,開始做我們的登陸接口login
登陸接口
參考之前的作業(yè),登錄接口的主邏輯我們這樣寫:
f=open('user.info','rb')
user_dict=pickle.load(f)
f.close()
while True:
username=input('Enter your account:')
password=input('Enter your password:')
if username not in user_dict:
print('Sorry,your account is not exist!\n')
continue
else:
if user_dict[username]['passwd'] != password:
print ('Sorry,your password invalid!\nPlease try again!\n')
continue
else:
print ('Welcome {}!'.format(username))
break
輸入帳號密碼,判斷是否存在用戶,之后判斷密碼是否是字典里用戶名對應的二級字典'passwd'對應的value,稍后這個需要做成裝飾器,我們先做成一個可調(diào)用的函數(shù)形式:
def login():
f=open('user.info','rb')
user_dict=pickle.load(f)
f.close()
while True:
username=input('Enter your account:')
password=input('Enter your password:')
if username not in user_dict:
print('Sorry,your account is not exist!\n')
continue
else:
if user_dict[username]['passwd'] != password:
print ('Sorry,your password invalid!\nPlease try again!\n')
continue
else:
print ('Welcome {}!'.format(username))
break
return username
函數(shù)返回的值我們暫時定為輸入的用戶名。
還有一個凍結(jié)賬戶的需求,這里還需要有個blacklist.txt
用來存放被凍結(jié)的賬戶,參考之前的作業(yè),黑名單做成列表,存放用戶名,pickle序列化到文件里。
在初始化腳本里加上創(chuàng)建blacklist.txt
文件的代碼:
import pickle
info_dict={'root':{'passwd':'python','balance':10000},
'test':{'passwd':'test','balance':10000}}
blacklist=['blacklist']
f=open('user.info','wb')
pickle.dump(info_dict,f)
f.close()
pro_list=[['iphone', 6200], ['mac pro', 12000], ['bike', 800], ['book', 55], ['coffee', 31], ['windows pc', 4900]]
f=open('product.txt','wb')
pickle.dump(pro_list,f)
f.close()
f=open('blacklist.txt','wb')
pickle.dump(blacklist,f)
f.close()
創(chuàng)建好之后,完善登錄接口的邏輯,我們把user.info文件寫成變量info_path,取得值是本文件所在目錄下的'user.info',黑名單文件同理也這么寫:
#owner:houyizhong
#version:1.0
import pickle
import os
filename=os.path.abspath(__file__)
dirname=os.path.dirname(filename)
info_path=dirname+os.sep+'user.info'
blackfile_path=dirname+os.sep+'blacklist.txt'
def login():
f=open(info_path,'rb')
user_dict=pickle.load(f)
f.close()
blackfile=open(blackfile_path,'rb')
blacklist=pickle.load(blackfile)
blackfile.close()
while True:
username=input('Enter your account:')
password=input('Enter your password:')
if username not in user_dict:
print('Sorry,your account is not exist!\n')
continue
elif username in blacklist:
print ("Sorry you are in blacklist!")
continue
else:
if user_dict[username]['passwd'] != password:
print ('Sorry,your password invalid!\nPlease try again!\n')
continue
else:
print ('Welcome {}!'.format(username))
break
return username
新增邏輯對blacklist.txt
的讀取列表,登錄接口里對用戶輸入的用戶名的判斷,是否在列表里。
信用卡
登錄接口完成之后,我們再來一一實現(xiàn)信用卡功能的各個模塊。
我把信用卡功能分為消費(即支付),查余額,查賬單,轉(zhuǎn)賬,提現(xiàn),還款等功能塊。我們一個個來實現(xiàn)。
還記得我們的賬戶余額是寫在用戶信息的文件里,作為二級字典的value存在的嗎?消費,轉(zhuǎn)賬,提現(xiàn),還款都要對余額有個修改操作,我們可以統(tǒng)一做成一個寫入余額的功能模塊。
實現(xiàn)寫入文件的模塊balance_module
:
import pickle
import os
filename=os.path.abspath(__file__)
dirname=os.path.dirname(filename)
info_path=dirname+os.sep+'user.info'
def write_balance(data):
f=open(info_path,'wb')
pickle.dump(data,f)
f.close()
上面的代碼,我是打開相對路徑下的user.info
文件,其實是跟balance_module是屬于同一目錄的,寫成info_path可以方便日后遷移user.info
路徑。
函數(shù)write_balance
接受的是一個字典,模塊會把這個字典寫入文件,覆蓋之前的內(nèi)容,這就要求我們傳入的字典是帶有所有用戶信息的,一個已經(jīng)調(diào)整好的字典,不會再有變動了。
這樣寫的好處是,所有信息修改完成之后,才會寫入文件,這樣下次讀取的文件內(nèi)容就是最新的了。這個道理我們在上一篇中已經(jīng)探討過。
讀取user.info
文件的函數(shù)
info_path的路徑即為user.info
的相對于credit.py
的位置
filename=os.path.abspath(__file__)
dirname=os.path.dirname(filename)
info_path=dirname+os.sep+'user.info'
def read_info():
f=open(info_path,'rb')
data=pickle.load(f)
f.close()
return data
返回的data
是提取出來的字典。
一些基本動作
我們在寫程序時,常常會遇到一些動作是頻繁做的,比如扣除余額(消費,提現(xiàn),轉(zhuǎn)賬都會用到),添加余額(還款,收到轉(zhuǎn)賬),還有判斷余額是否充足,是否滿足動作(消費,提現(xiàn))所需的金額。這些可以復用的代碼,我們就把它做成函數(shù),需要時調(diào)用好了。
def add(username,bill,data):
balance=data[username]['balance']
balance += bill
data[username]['balance']=balance
return data
def subtract(username,bill,data):
balance=data[username]['balance']
balance -= bill
data[username]['balance']=balance
print ('Your balance is {}\n'.format(balance))
return data
def judgment(username,bill):
data=read_info()
balance=data[username]['balance']
if balance >= bill:
return 'success'
else:
print ('Your balance is not enought!\n')
return 'failure'
余額的刪減都需要對整個字典進行修改(這樣返回數(shù)據(jù)時,接受數(shù)據(jù)的模塊處理更方便,直接把data寫入文件),判斷余額是否滿足動作所需金額bill的函數(shù),我們返回是'success'和'failure',這樣調(diào)用函數(shù)的模塊更容易判斷是否滿足,直接根據(jù)收到的字符來判斷。
日志記錄
我們要有日志記錄功能,記錄我們每一次的消費,要有消費時間,消費項目,金額,消費記錄這個動作做成模塊,其他模塊可以復用:
def consumer_logger(username,stock,price):
user_dir=log_path+os.sep+username
if not os.path.exists(user_dir):
os.mkdir(user_dir)
cust_log=user_dir+os.sep+'cust.log'
times=time.strftime('%Y%m%d%H%M%S')
data='{0}\t{1}\t{2}'.format(times,stock,price)
log=open(cust_log,'a')
log.write('{}\n'.format(data))
log.close()
我們的日志是放在logs目錄下的,同時還要根據(jù)用戶不同創(chuàng)建不同的日志信息,這樣方便區(qū)分。
我們用user_dir代表logs下的用戶文件夾,當不存在時,創(chuàng)建文件夾
cust_log代表用戶文件夾下的cust.log文件,具體的信息盛放在里面。
接受的形參分別代表用戶名,商品名(購物車列表),金額
調(diào)用time模塊,用time.strftime()
方法取到年月日小時分秒級別的時間,用制表符寫入文件
同理,atm操作記錄也這么寫
def atm_logger(username,operating,money):
user_dir=log_path+os.sep+username
if not os.path.exists(user_dir):
os.mkdir(user_dir)
atm_log=user_dir+os.sep+'atm.log'
times=time.strftime('%Y%m%d%H%M%S')
data='{0}\t{1}\t{2}'.format(times,operating,money)
log=open(atm_log,'a')
log.write('{}\n'.format(data))
log.close()
接受的形參分別為用戶名,動作,金額。
支付模塊
我們寫一個支付函數(shù)payment來實現(xiàn)邏輯:
import balance_module
def payment(shoplist,bill):
data=read_info()
username=login()
result=judgment(username,bill)
if result == 'success':
data=subtract(username,bill,data)
balance_module.write_balance(data)
consumer_logger(username,shoplist,bill)
return result
可以看到我們需要調(diào)用用戶認證接口,因為到付款界面了,必須知道銀行賬戶。
調(diào)用了讀取用戶信息字典的read_info()
函數(shù),將字典提取出來
調(diào)用了judgment()
來判斷用戶對應的余額是否滿足
如果收到的是'success',調(diào)用扣除余額的函數(shù),將字典寫入文件的函數(shù),消費日志記錄函數(shù)
以上函數(shù)我們都已經(jīng)寫出來了。
然后函數(shù)返回的結(jié)果是成功或者失敗。很容易理解對吧。
轉(zhuǎn)賬模塊就是一個用戶余額減少,另一個用戶余額增加,可以這么寫(為了直觀,我沒有把add()
subtract()
judgment()
atm_logger()
這些調(diào)用的函數(shù)寫出來,下面幾個也是如此):
import balance_module
def transfer():
username=login()
data=read_info()
transfer_account=input('Enter transfer account:')
transfer_money=input('Enter transfer money:')
if transfer_account in data:
if transfer_money.isdigit:
transfer_money=float(transfer_money)
result=judgment(username,transfer_money)
if result == 'success':
data=subtract(username,transfer_money,data)
data=add(transfer_account,transfer_money,data)
print ('Your transfer done!\n')
balance_module.write_balance(data)
atm_logger(username,'transfer',transfer_money)
elif result == 'failure':
print ('Your balance is not enought!\n')
else:
print ('Sorry,there have some unknown error!\n')
else:
print ('Sorry,your enter money is not a digit!\n')
else:
print('Sorry,your enter account is not exist!\n')
提現(xiàn)模塊也很好寫,用戶余額減少,同時判斷余額一半是否大于提現(xiàn)的金額:
import balance_module
def withdraw():
username=login()
data=read_info()
withdraw_money=input('Enter your withdraw money:')
if withdraw_money.isdigit():
cost_money=float(withdraw_money)*(1+0.05)
result=judgment(username,cost_money)
withdraw_money=float(withdraw_money)
if result == 'success':
if withdraw_money > (data[username]['balance']/2):
print ('Sorry,your withdraw money is more than avalid balance!\n')
else:
data=subtract(username,cost_money,data)
balance_module.write_balance(data)
atm_logger(username,'withdraw',cost_money)
print ('Your withdraw done!\n')
else:
print('Sorry,you enter is not digit!\n')
也是調(diào)用了一堆現(xiàn)成的函數(shù),把它們拼貼起來。
還款,就是新增余額:
import balance_module
def repay():
username=login()
data=read_info()
repay_money=input('Enter your repay money:')
if repay_money.isdigit():
repay_money=float(repay_money)
data=add(username,repay_money,data)
balance_module.write_balance(data)
atm_logger(username,'repay',repay_money)
print('Your repay done!\n')
else:
print('Sorry,your enter is not digit!\n')
以上幾個函數(shù)基本實現(xiàn)了一個信用卡的基本功能
完整的代碼
#owner:houyizhong
#version:1.0
import pickle,time,os
import balance_module
from demo_login import login
filename=os.path.abspath(__file__)
dirname=os.path.dirname(filename)
info_path=dirname+os.sep+'user.info'
log_path=os.path.dirname(dirname)+os.sep+'logs'
def read_info():
f=open(info_path,'rb')
data=pickle.load(f)
f.close()
return data
def add(username,bill,data):
balance=data[username]['balance']
balance += bill
data[username]['balance']=balance
return data
def subtract(username,bill,data):
balance=data[username]['balance']
balance -= bill
data[username]['balance']=balance
print ('Your balance is {}\n'.format(balance))
return data
def judgment(username,bill):
data=read_info()
balance=data[username]['balance']
if balance >= bill:
return 'success'
else:
print ('Your balance is not enought!\n')
return 'failure'
def atm_logger(username,operating,money):
user_dir=log_path+os.sep+username
if not os.path.exists(user_dir):
os.mkdir(user_dir)
atm_log=user_dir+os.sep+'atm.log'
times=time.strftime('%Y%m%d%H%M%S')
data='{0}\t{1}\t{2}'.format(times,operating,money)
log=open(atm_log,'a')
log.write('{}\n'.format(data))
log.close()
def consumer_logger(username,stock,price):
user_dir=log_path+os.sep+username
if not os.path.exists(user_dir):
os.mkdir(user_dir)
cust_log=user_dir+os.sep+'cust.log'
times=time.strftime('%Y%m%d%H%M%S')
data='{0}\t{1}\t{2}'.format(times,stock,price)
log=open(cust_log,'a')
log.write('{}\n'.format(data))
log.close()
def inquire():
data=read_info()
username=login()
print('Your balance is :')
print(data[username]['balance'])
def payment(shoplist,bill):
data=read_info()
username=login()
result=judgment(username,bill)
if result == 'success':
data=subtract(username,bill,data)
balance_module.write_balance(data)
consumer_logger(username,shoplist,bill)
return result
def transfer():
username=login()
data=read_info()
transfer_account=input('Enter transfer account:')
transfer_money=input('Enter transfer money:')
if transfer_account in data:
if transfer_money.isdigit:
transfer_money=float(transfer_money)
result=judgment(username,transfer_money)
if result == 'success':
data=subtract(username,transfer_money,data)
data=add(transfer_account,transfer_money,data)
print ('Your transfer done!\n')
balance_module.write_balance(data)
atm_logger(username,'transfer',transfer_money)
elif result == 'failure':
print ('Your balance is not enought!\n')
else:
print ('Sorry,there have some unknown error!\n')
else:
print ('Sorry,your enter money is not a digit!\n')
else:
print('Sorry,your enter account is not exist!\n')
def withdraw():
username=login()
data=read_info()
withdraw_money=input('Enter your withdraw money:')
if withdraw_money.isdigit():
cost_money=float(withdraw_money)*(1+0.05)
result=judgment(username,cost_money)
withdraw_money=float(withdraw_money)
if result == 'success':
if withdraw_money > (data[username]['balance']/2):
print ('Sorry,your withdraw money is more than avalid balance!\n')
else:
data=subtract(username,cost_money,data)
balance_module.write_balance(data)
atm_logger(username,'withdraw',cost_money)
print ('Your withdraw done!\n')
else:
print('Sorry,you enter is not digit!\n')
def repay():
username=login()
data=read_info()
repay_money=input('Enter your repay money:')
if repay_money.isdigit():
repay_money=float(repay_money)
data=add(username,repay_money,data)
balance_module.write_balance(data)
atm_logger(username,'repay',repay_money)
print('Your repay done!\n')
else:
print('Sorry,your enter is not digit!\n')
單獨測試每個模塊也是沒問題的。這樣 我們就可以繼續(xù)寫下去了。
購物車程序
這里可以參考之前的作業(yè),再加上一個調(diào)用信用卡模塊
import pickle,os
import demo_credit
filename=os.path.abspath(__file__)
dirname=os.path.dirname(filename)
product_path=dirname+os.sep+'product.txt'
def shopping():
shopping_list=[]
price=0
'''read product'''
f=open(product_path,'rb')
product_list=pickle.load(f)
f.close()
def credit_payment(shoplist,price):
result=demo_credit.payment(shoplist,price)
if result == 'success':
print ('You shopping done!')
elif result == 'failure':
print ('Sorry,your credit card balance is not enought!\n')
else:
print('Sorry,there have some unknown error!\n')
while True:
for index,item in enumerate(product_list):
print(index+1,item)
user_choice=input("Choice a product code('q' is exit.'pay' is settlement):")
if user_choice.isdigit():
user_choice = int(user_choice)
if user_choice <= len(product_list) and user_choice > 0:
user_choice -= 1
price += int(product_list[user_choice][1])
shopping_list.append(product_list[user_choice][0])
print ('Add {} to your shopplist!\n'.format(product_list[user_choice][0]))
else:
print("Sorry,product code isn's exist!\n")
elif user_choice == "q":
break
elif user_choice == 'pay':
print('Your check is {}'.format(price))
if price != 0:
credit_payment(shopping_list,price)
break
else:
print("Your enter invalid!\n")
我們先進入while循環(huán),打印商品列表,讓用戶輸入選擇,加入購物車列表,q是退出,pay是支付,當金額是0時不需要調(diào)用信用卡模塊。
支付大于0時調(diào)用信用卡模塊,進入支付接口,從支付接口那里收到'success'或者'failure'的判斷,做成相應動作。
然后是管理模塊
也是參考之前的作業(yè),調(diào)用現(xiàn)成的函數(shù),就完成了
import pickle,os
import balance_module
filename=os.path.abspath(__file__)
dirname=os.path.dirname(filename)
info_path=dirname+os.sep+'user.info'
blackfile_path=dirname+os.sep+'blacklist.txt'
def read_info():
f=open(info_path,'rb')
data=pickle.load(f)
f.close()
return data
def add_account():
data=read_info()
count_name=input('Enter add account("b" is back):')
if count_name == 'b':
pass
else:
count_balance=input('Enter account balance("b" is back):')
if count_balance.isdigit():
count_balance=int(count_balance)
count_passwd=input('Enter account password("b" is back):')
if count_passwd == 'b':
pass
else:
data[count_name]={'passwd':count_passwd,'balance':count_balance}
balance_module.write_balance(data)
print('Done')
elif count_balance == 'b':
pass
else:
print('Sorry,your enter balance is not digit!\n')
def change_account():
data=read_info()
change_name=input('Enter change account name:')
if change_name in data:
change_balance=input('Enter change account balance:')
if change_balance.isdigit():
change_balance=int(change_balance)
data[change_name]['balance']=change_balance
balance_module.write_balance(data)
print ('Done')
elif change_balance == 'b':
pass
else:
print('Sorry,your enter is not digit!\n')
elif change_name == 'b':
pass
else:
print ('Sorry,your choose account is not exist!\n')
def blacklist():
f=open(blackfile_path,'rb')
list=pickle.load(f)
f.close()
data=read_info()
blacklist_name=input('Enter blacklist account name:')
if blacklist_name in data:
list.append(blacklist_name)
f=open(blackfile_path,'wb')
pickle.dump(list)
f.close()
elif blacklist_name == 'b':
pass
else:
print ('Sorry,you choose account is not exist!\n')
完成這些之后,我們來到bin目錄下實現(xiàn)啟動接口
購物車接口
這邊只是需要調(diào)用購物車模塊,只是需要注意現(xiàn)在購物車程序跟核心模塊不在一個目錄里,注意調(diào)用模塊時的路徑
import os,sys
BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
CORE_DIR=BASE_DIR+os.sep+'core'
sys.path.append(BASE_DIR)
sys.path.append(CORE_DIR)
import core
core.demo_shoplist.shopping()
把core目錄放進系統(tǒng)變量,調(diào)用下面的模塊文件
管理程序
import os,sys
BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
CORE_DIR=BASE_DIR+os.sep+'core'
sys.path.append(BASE_DIR)
sys.path.append(CORE_DIR)
from core import demo_manage
action_list=['Add account','Edit account','Block account']
while True:
for index,item in enumerate(action_list):
print(index+1,item)
print('"q" is exit.')
enter_action=input('Enter your choice:')
if enter_action.isdigit():
if enter_action == '1':
demo_manage.add_account()
continue
elif enter_action == '2':
demo_manage.change_account()
continue
elif enter_action == '3':
demo_manage.blacklist()
continue
else:
if enter_action == 'q':
exit()
else:
print('Sorry,your enter invaild!\n')
也是要把core目錄放進系統(tǒng)變量里。
atm啟動接口
import os
import sys
BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
CORE_DIR=BASE_DIR+os.sep+'core'
sys.path.append(BASE_DIR)
sys.path.append(CORE_DIR)
from core import demo_credit
action_list=['Query check','Transfer','Query balance','Withdraw','Repay']
while True:
for index,item in enumerate(action_list):
print(index+1,item)
print('"q" is exit.')
enter_action=input('Enter your choice:')
if enter_action.isdigit():
if enter_action == '1':
'''Query check'''
continue
elif enter_action == '2':
'''Transfer'''
demo_credit.transfer()
continue
elif enter_action == '3':
'''Query balance'''
demo_credit.inquire()
continue
elif enter_action == '4':
'''Withdraw'''
demo_credit.withdraw()
continue
elif enter_action == '5':
'''Repay'''
demo_credit.repay()
continue
else:
print ('Sorry,you enter invaild!\n')
continue
else:
if enter_action == 'q':
exit()
else:
print('Sorry,your enter invaild!\n')
主要是打印可操作項,對輸入做判斷,調(diào)用響應的模塊,也是需要注意模塊調(diào)用時的添加系統(tǒng)變量。
用戶認證用裝飾器
裝飾器的樣式這樣:
def login(func):
def decorator(*args,**kwargs):
func(*args,**kwargs)
return decorator
@login
def func():
pass
func()
我們對login()
函數(shù)進行改造
import pickle
import os
filename=os.path.abspath(__file__)
dirname=os.path.dirname(filename)
info_path=dirname+os.sep+'user.info'
blackfile_path=dirname+os.sep+'blacklist.txt'
def login(func):
def decorator(*args,**kwargs):
f=open(info_path,'rb')
user_dict=pickle.load(f)
f.close()
blackfile=open(blackfile_path,'rb')
blacklist=pickle.load(blackfile)
blackfile.close()
while True:
username=input('Enter your account:')
password=input('Enter your password:')
if username not in user_dict:
print('Sorry,your account is not exist!\n')
continue
elif username in blacklist:
print ("Sorry you are in blacklist!")
continue
else:
if user_dict[username]['passwd'] != password:
print ('Sorry,your password invalid!\nPlease try again!\n')
continue
else:
print ('Welcome {}!'.format(username))
break
func(username,*agrs,**kwargs)
return decorator
@login
def func(username):
print(username)
func()
這樣測試,可以正常實現(xiàn)功能,現(xiàn)在要融入其他模塊中。
在同級目錄下寫一個測試文件
from demo_login import login
@login
def func(username):
print(username)
func()
測試,可以實現(xiàn),于是移植到其他模塊里。
import pickle,time,os
import balance_module
from demo_login import login
filename=os.path.abspath(__file__)
dirname=os.path.dirname(filename)
info_path=dirname+os.sep+'user.info'
log_path=os.path.dirname(dirname)+os.sep+'logs'
@login
def query(username):
user_dir=log_path+os.sep+username
if not os.path.exists(user_dir):
print('Sorry,you do not have check.')
else:
cust_log=user_dir+os.sep+'cust.log'
if os.path.exists(cust_log):
log=open(cust_log,'r')
print('You check is:')
print(log.read())
log.close()
else:
print('Sorry,you do not have check.')
@login
def inquire(username):
data=read_info()
print('Your balance is :')
print(data[username]['balance'])
@login
def payment(username,shoplist,bill):
data=read_info()
result=judgment(username,bill)
if result == 'success':
data=subtract(username,bill,data)
balance_module.write_balance(data)
consumer_logger(username,shoplist,bill)
return result
@login
def transfer(username):
data=read_info()
transfer_account=input('Enter transfer account:')
transfer_money=input('Enter transfer money:')
if transfer_account in data:
if transfer_money.isdigit:
transfer_money=float(transfer_money)
result=judgment(username,transfer_money)
if result == 'success':
data=subtract(username,transfer_money,data)
data=add(transfer_account,transfer_money,data)
print ('Your transfer done!\n')
balance_module.write_balance(data)
atm_logger(username,'transfer',transfer_money)
elif result == 'failure':
print ('Your balance is not enought!\n')
else:
print ('Sorry,there have some unknown error!\n')
else:
print ('Sorry,your enter money is not a digit!\n')
else:
print('Sorry,your enter account is not exist!\n')
@login
def withdraw(username):
data=read_info()
withdraw_money=input('Enter your withdraw money:')
if withdraw_money.isdigit():
cost_money=float(withdraw_money)*(1+0.05)
result=judgment(username,cost_money)
withdraw_money=float(withdraw_money)
if result == 'success':
if withdraw_money > (data[username]['balance']/2):
print ('Sorry,your withdraw money is more than avalid balance!\n')
else:
data=subtract(username,cost_money,data)
balance_module.write_balance(data)
atm_logger(username,'withdraw',cost_money)
print ('Your withdraw done!\n')
else:
print('Soory,you enter is not digit!\n')
@login
def repay(username):
data=read_info()
repay_money=input('Enter your repay money:')
if repay_money.isdigit():
repay_money=float(repay_money)
data=add(username,repay_money,data)
balance_module.write_balance(data)
atm_logger(username,'repay',repay_money)
print('Your repay done!\n')
else:
print('Sorry,your enter is not digit!\n')
測試可以實現(xiàn)功能
注意不止credit.py
需要用到認證,其他文件可能也需要,像是shoplist.py
。代碼如下:
import pickle,os
from demo_login import login
import demo_credit
filename=os.path.abspath(__file__)
dirname=os.path.dirname(filename)
product_path=dirname+os.sep+'product.txt'
def shopping():
shopping_list=[]
price=0
'''read product'''
f=open(product_path,'rb')
product_list=pickle.load(f)
f.close()
@login
def credit_payment(username,shoplist,price):
result=demo_credit.payment(username,shoplist,price)
if result == 'success':
print ('You shopping done!')
elif result == 'failure':
print ('Sorry,your credit card balance is not enought!\n')
else:
print('Sorry,there have some unknown error!\n')
while True:
for index,item in enumerate(product_list):
print(index+1,item)
user_choice=input("Choice a product code('q' is exit.'pay' is settlement):")
if user_choice.isdigit():
user_choice = int(user_choice)
if user_choice <= len(product_list) and user_choice > 0:
user_choice -= 1
price += int(product_list[user_choice][1])
shopping_list.append(product_list[user_choice][0])
print ('Add {} to your shopplist!\n'.format(product_list[user_choice][0]))
else:
print("Sorry,product code isn's exist!\n")
elif user_choice == "q":
break
elif user_choice == 'pay':
print('Your check is {}'.format(price))
if price != 0:
credit_payment(shopping_list,price)
break
else:
print("Your enter invalid!\n")
這里用了之后,credit.py
里的paymant()
函數(shù)就可以去掉裝飾器了。
坑:
- 所有用的文件都需要寫成變量形式啊,因為啟動入口目錄下面沒有啊,而且不能寫死,必須用
os.path.dirname
方式加os.sep
加文件名拼貼才行啊!! - credit里的
consumer_logger()
函數(shù)需要按不同賬戶創(chuàng)建不同的log啊啊啊! - 自己寫的模塊A import了另一個自己寫的模塊B,啟動程序那里還需要加上模塊B所在路徑的系統(tǒng)搜索路徑啊~不然from package import 模塊A的時候,模塊A再import 模塊B,這個時候不知道從哪里找模塊B,因為啟動程序的系統(tǒng)路徑里找不到模塊B;如果是import package,運行
__init__.py
的時候,from . import 模塊B,這個時候啟動程序的系統(tǒng)搜索路徑里也找不到B。