close

博翔科技為專業機械設備歐規/台灣TS標章/美規及半導體設備SEMI S2輔導顧問公司

博翔對於各類機械的安全技術 安全開關 安全模組 安全繼電器模組 安全繼電器 緊急停止 安全元件 歐盟電路設計 安全迴路 安全設計

由於科技的進步,各種無線通訊設備及數位裝置技術的高度發展,電磁干擾已成為電子時代中世界各國關注的問題。

機械產品的製造為迎向消費市場需求,亦朝向高速度、高精度、自動化且大量使用數值控制而使機械產品電磁干擾問題更加複雜

而博翔科技協助您解決相關安全技術問題以專業級檢測與規畫經驗並協助各種機械廠快速獲得相關認證

邀請您一起邁向世界的安全技術頂端

請立即點擊上方圖片了解更多細節吧!

 

好文分享

 

ATM購物車項目 模擬實現一個ATM + 購物商城程序。 該程序實現普通用戶的登錄註冊、提現充值還款等功能,並且支持到網上商城購物的功能。 帳戶餘額足夠支付商品價格時,扣款支付;餘額不足時,無法支付,商品存放個人購物車。 如果用戶具有管理員功能,還支持管理員身份登錄。具體需求見項目需求部分。 三層架構 項目開發中,清晰明了的結構設計非常重要。它的重要性至少體現在三個方面:結構清晰;可維護性強;可擴展性高。 常用的項目結構設計中,三層架構設計非常實用。這種架構設計模式將整個程序分為三層: 用戶視圖層:用戶交互的,可以接受用戶的輸入數據,展示顯示的消息。 邏輯接口層:接收視圖層傳遞過來的參數,根據邏輯判斷調用數據層加以處理並返回一個結果給用戶視圖層。 數據處理層:接受接口層傳遞過來的參數,做數據的增刪改查。 Copy# 優點:結構清晰,職責明了。擴展性強,好維護。對數據比較安全。 # 缺點:每個功能都要跨越邏輯接口層,不能直接訪問資料庫,所以效率會降下來。 ... 項目需求 Copy1.額度15000或自定義 --> 註冊功能 2.實現購物商城,買東西加入購物車,調用信用卡接口結帳 --> 購物功能、支付功能 3.可以提現,手續費5% --> 提現功能 4.支持多帳戶登錄 --> 登錄功能,登錄失敗三次凍結帳戶 5.支持帳戶間轉帳 --> 轉帳功能 6.記錄日常消費 --> 記錄流水功能 7.提供還款接口 --> 還款功能 8.ATM記錄操作日誌 --> 記錄日誌功能 9.提供管理接口,包括添加帳戶、用戶額度,凍結帳戶等。。。 ---> 管理員功能 10.用戶認證用裝飾器 --> 登錄認證裝飾器 提取功能 Copy# 展示給用戶選擇的功能(用戶視圖層) 1、註冊功能 2、登錄功能 3、查看餘額 4、提現功能 5、還款功能 6、轉帳功能 7、查看流水 8、購物功能 9、查看購物車 10、管理員功能 實現思路 上一篇項目總結也是關於ATM,只不過那個項目中所有的函數都在一個py文件中;這個項目總結不能再那樣搞了,這次要規範點。 我們知道軟體開發目錄規範,就是按程序的不同功能將代碼分布在不同的文件(夾)中,本項目也採用這種規範。 另外,我們又學習了項目的三層架構設計,將一個功能分三個層次,清晰各部分職責。 所以,這個項目基於軟體開發目錄規範,採用三層架構的原則,編寫每個具體功能的代碼。 項目框架 整個項目採用三層結構設計。用戶直接接觸的是用戶視圖層。用戶通過選擇不同的功能,進入不同功能的用戶視圖層。 在用戶視圖層中,用戶輸入數據;然後用戶視圖層將用戶的數據傳給邏輯接口層,邏輯接口層調用數據處理層的接口,獲取該用戶的相關數據,做一定的邏輯判斷,然後將邏輯判斷後的數據和/或信息返回到用戶視圖層,展示給用戶。 ... 程序結構:遵循軟體開目錄規範 CopyATM&Shop/ |-- conf | |-- setting.py # 項目配置文件 |-- core | |-- admin.py # 管理員視圖層函數 | |-- current_user.py # 記錄當前登錄用戶信息[username, is_admin] | |-- shop.py # 購物相關視圖層函數 | |-- src.py # 主程序(包含用戶視圖層函數、atm主函數) |-- db | |-- db_handle.py # 數據處理層函數 | |-- goods_data.json # 商品信息文件 | |-- users_data # 用戶信息json文件夾 | | |-- xliu.json # 用戶信息文件:username|password|balance|my_flow|my_cart等 | | |-- egon.json |-- interface # 邏輯接口 | |-- admin_interface.py # 管理員邏輯接口層函數 | |-- bank_interface.py # 銀行相關邏輯接口層函數 | |-- shop_interface.py # 購物相關邏輯接口層函數 | |-- user_interface.py # 用戶相關邏輯接口層函數 |-- lib | |-- tools.py # 公用函數:加密|登錄裝飾器權限校驗|記錄流水|日誌等 |-- log # 日誌文件夾 | |-- operation.log | |-- transaction.log |-- readme.md |-- run.py # 項目啟動文件 運行環境 Copy- windows10, 64位 - python3.8 - pycharm2019.3 註冊功能三層架構分析 註冊功能用戶視圖層:core/src.py Copyfrom lib.tools import hash_md5, auto from core.current_user import login_user from interface.user_interface import register_interface @auto('註冊') def register(): print('註冊頁面'.center(50, '-')) while 1: name = input('請輸入用戶名:').strip() pwd = input('請輸入密碼:').strip() re_pwd = input('請確認密碼:').strip() if pwd != re_pwd: print('兩次密碼輸入不一致,請重新輸入') continue flag, msg = register_interface(name, hash_md5(pwd)) print(msg) if flag: break # 註冊功能用戶視圖層接收用戶的註冊信息:用戶名|密碼|確認密碼 # 先做一個小邏輯判斷,判斷密碼和確認密碼是否一致?若不一致,則提示用戶密碼不一致從新輸入 # 若密碼一致,則將用戶名和密碼後的密碼通過註冊接口交給邏輯接口層 # 然後接受邏輯接口層的返回數據和信息,列印展示和下一步判斷。 註冊功能邏輯接口層:interface/user_interface.py Copyfrom conf.settings import INIT_BALANCE from core.current_user import login_user from db import db_handle from lib.tools import save_log def register_interface(name, pwd): """ 註冊接口 :param name: :param pwd: 密碼,密文 :return: """ user_dict = db_handle.get_user_info(name) if user_dict: return False, '用戶名已經存在' user_dict = { 'username': name, 'password': pwd, 'balance': INIT_BALANCE, 'is_admin': False, 'is_locked': False, 'login_failed_counts': 0, 'my_cart': {}, 'my_flow':{} } save_log('日常操作').info(f'{name}註冊帳號成功') db_handle.save_user_info(user_dict) return True, '註冊成功' # 註冊功能邏輯接口層接收用戶視圖層傳過來的用戶名和密文密碼, # 通過調用數據處理層get_user_info函數,讀用戶文件,獲取用戶的信息字典 # 若用戶信息字典存在,則該用戶名已經被註冊使用,則返回給用戶視圖層不能註冊的信息 # 若用戶信息字典不存在,則說明可以註冊。 # 創建新用戶信息字典,初始化相關數據,交給數據處理層save_user_info函數,並返回給用戶視圖層可以註冊的信息。 數據處理層:db/db_handle.py Copyimport os, json from conf.settings import USER_DB_DIR def get_user_info(name): user_file = os.path.join(USER_DB_DIR, f'{name}.json') if os.path.isfile(user_file): with open(user_file, 'rt', encoding='utf-8') as f: return json.load(f) else: return {} def save_user_info(user_dict): user_dict['balance'] = round(user_dict['balance'], 2) user_file = os.path.join(USER_DB_DIR, f'{user_dict.get("username")}.json') with open(user_file, 'wt', encoding='utf-8') as f: json.dump(user_dict, f, ensure_ascii=False) # 數據處理層函數:通過用戶名獲取用戶信息字典;若用戶存在則返回用戶信息字典,用戶不存在則返回空字典 # save_user_info函數,接收邏輯接口層的接口,將用戶信息字典序列化保存到獨立文件,以用戶名命名文件名 提現功能三層結構分析 提現功能用戶視圖層:core/src.py Copyfrom lib.tools import auth, is_number, auto from core.current_user import login_user from interface.bank_interface import withdraw_interface @auto('提現') @auth def withdraw(): print('提現頁面'.center(50, '-')) while 1: amounts = input('請輸入體現金額:').strip() if not is_number(amounts): print('請輸入合法的體現金額') continue flag, msg = withdraw_interface(login_user[0], float(amounts)) print(msg) if flag: break # 提現功能用戶視圖層:在用在用戶登錄之後才能使用(利用函數裝飾器auth實現登錄校驗) # 接收用戶輸入提現金額,先做小邏輯判斷用戶輸入金額是否是數字(支持小數),通過工具函數is_number實現 # 然後將合法提現金額轉成浮點數通過提現接口交給提現邏輯接口層 # 列印邏輯接口層返回的數據並做判斷 提現功能邏輯接口層:interface/bank_interface.py Copyfrom db import db_handle from conf.settings import SERVICE_FEE_RATIO from lib.tools import save_flow, save_log def withdraw_interface(name, amounts): user_dict = db_handle.get_user_info(name) amounts_and_fee = amounts * (1 + SERVICE_FEE_RATIO) if amounts_and_fee > user_dict.get('balance'): save_log('提現').info(f'{name}提現{amounts}元,餘額不足提現失敗') return False, '帳戶餘額不足' user_dict['balance'] -= amounts_and_fee msg = f'{name}提現{amounts}元' save_flow(user_dict, '提現', msg) save_log('提現').info(msg) db_handle.save_user_info(user_dict) return True, f'提現金額{amounts}元, 帳戶餘額:{user_dict["balance"]}元' # 通過用戶名調用數據處理層函數get_user_info獲取用戶信息字典金額獲取用戶的帳戶餘額 # 計算出用戶提現金額的本金和手續費,判斷本金和手續費是否大於帳戶餘額 # 若大於帳戶餘額,則無法提現,將提示信息返回給提現用戶視圖層 # 否則,從帳戶餘額中扣除提現金額和手續費 # 調用數據處理層save_user_info,保存用戶的信息 # 將提現成功信息返回給用戶視圖層 購物功能三層架構分析 購物功能用戶視圖層:core/shop.py Copyfrom core.current_user import login_user from lib.tools import auth, auto from conf.settings import GOODS_CATEGOTY from interface.shop_interface import get_goods_interface, shopping_interface from interface.shop_interface import put_in_mycart_interface @auto('網上商城') @auth def shopping(): print('網上商城'.center(50, '-')) username = login_user[0] new_goods = [] # 存放用戶本次選擇的商品 while 1: for k, v in GOODS_CATEGOTY.items(): print(f'({k}){v}') category = input('請選擇商品類型編號(結算Y/退出Q):').strip().lower() if category == 'y': if not new_goods: print('您本次沒有選擇商品,無法結算') continue else: flag, msg = shopping_interface(username, new_goods) print(msg) if not flag: put_in_mycart_interface(username, new_goods) break elif category == 'q': if not new_goods: break put_in_mycart_interface(username, new_goods) break if category not in GOODS_CATEGOTY: print('您選擇的編號不存在,請重新選擇') continue goods_list = get_goods_interface(GOODS_CATEGOTY[category]) while 1: for index, item in enumerate(goods_list, 1): name, price = item print(f'{index}: {name}, {price}元') choice = input('請輸入商品的編號(返回B):').strip().lower() if choice == 'b': break if not choice.isdigit() or int(choice) not in range(1, len(goods_list)+1): print('您輸入的商品編號不存在,請重新輸入') continue name, price = goods_list[int(choice)-1] counts = input(f'請輸入購買{name}的個數:').strip() if not counts.isdigit() and counts == '0': print('商品的個數是數字且不能為零') continue new_goods.append([name, price, int(counts)]) # 購物功能用戶視圖層:需要用戶先登錄再使用 # 列印商品分類表,讓用戶選擇分類編號,然後將分類編號傳給邏輯接口層,獲取該分類下的商品列表展示給用戶。 # 用戶繼續選擇該分類下的商品編號和購買的商品個數。此處會使用小邏輯判斷用戶的輸入是否合法。 # 選擇商品和商品個數後,會將選擇的結果臨時存放在列表new_goods中,用於用戶退出時結算。 # 如果用戶選擇支付,則將用戶名和用戶選擇的商品通過購物結構交給購物邏輯接口層。 # 若邏輯接口層返回的結果時支付成功,則退出購物;若返回的就過是支付失敗則將new_goods的商品交給put_in_mycart_interface放進購物車接口。 # 如果用戶選擇退出,則直接將new_goods的商品交給put_in_mycart_interface放進購物車接口 購物功能邏輯接口層:interface/shop_interface.py Copyfrom db import db_handle from interface.bank_interface import pay_interface from lib.tools import save_log def get_goods_interface(category): """ 根據分類獲取商品 :param category: :return: """ return db_handle.get_goods_info(category) def shopping_interface(name, new_goods): total_cost = 0 for item in new_goods: *_, price, counts = item total_cost += price * counts flag = pay_interface(name, total_cost) if flag: return True, '支付成功,商品發貨中....' else: return False, '帳戶餘額不足,支付失敗' def put_in_mycart_interface(name, new_goods): user_dict = db_handle.get_user_info(name) my_cart = user_dict.get('my_cart') for item in new_goods: goods_name, price, counts = item if goods_name not in my_cart: my_cart[goods_name] = [price, counts] else: my_cart[goods_name][-1] += counts save_log('日常操作').info(f'{name}更新了購物車商品') db_handle.save_user_info(user_dict) # 購物接口層函數,計算接收的商品的總價,然後調用並將總結交給銀行支付接口 # 支付接口返回支付成功/失敗的返回信息;若支付成功則返回給用戶視圖層支付成功的信息;否則是支付失敗的信息 # 放進購物車接口:將用戶石塗層傳過來的商品保存到用戶信息字典裡面的my_cart字典中,並調用數據處理層的save_user_info含糊,保存用戶信息。 # 獲取商品接口get_goods_interface,接收用戶視圖層傳過來的商品分類。然後將該分類信息返回給用戶視圖層 購物功能數據處理層:db/db_handle.py Copy...... from conf.settings import GOODS_DB_FILE def get_goods_info(category): with open(GOODS_DB_FILE, 'rt', encoding='utf-8') as f: all_goods_dict = json.load(f) return all_goods_dict.get(category) # 這個函數主要用來接收購物功能邏輯接口層get_goods_interface函數請求的商品分類,獲取該分類下的所有商品返回給邏輯接口層再返回給用戶視圖層。 小知識點總結 json文件中文字符顯示問題 Copyimport json with open(user_file, 'wt', encoding='utf-8') as f: json.dump(user_dict, f, ensure_ascii=False) # 由於json序列化是可讀序列化,即json文件存放的是字符串類型的數據(不像pickle是二進位不可讀的數據)。 # 此外,json文件存放的是unic0de text。即如果存的字符是中午字符,則會被存儲為unicode二進位數據,在這json文件裡面看起來很不舒服。 # 這個問題可以通過 json.dump中的參數ensure_ascii=False解決,即中文字符不會轉為二進位字節 資金的小數點保留問題 Copy# 本項目就涉及用戶金額數據小數點保留問題。對於會計金融需要非常在意小數點保留問題上,不能簡單使用int轉整形 # 還不能使用float保留成浮點型,因為它的精度不夠,且小數位不能控制 # 你可能會說round(1.2312, 2)可以設置小數點精度; 但round(0.00001, 2),想要的結果是0.01而得到的結果確實0.0 # 此時可以導入decimal模塊 import decimal s = decimal.Decimal('0.00001') print(s, type(s)) # 0.00001 <class 'decimal.Decimal'> print(s.quantize(decimal.Decimal('0.01'), 'ROUND_UP')) # 0.01 # 可惜的是本項目使用的是json文件,好像不能存decimal類型的數據。獲取再轉成字符串也行吧,回來再試試。 re模塊匹配數字應用在項目中 Copyimport re def is_number(your_str): res = re.findall('^d+.?d*

TTT77941YYDDEE156365GG

, your_str) if res: return True else: return False # 匹配數字,判斷輸入的字符串是否是非負數 hash模塊項目中密碼加密 Copyimport hashlib def hash_md5(info): m = hashlib.md5() m.update(info.encode('utf-8')) m.update('因為相信所以看見'.encode('utf-8')) # 加鹽處理 return m.hexdigest() # 用於密碼加密 logging模塊項目中記錄日誌 Copy# 使用流程: -1 在配置文件settings.py中配置日誌字典LOGGING_DIC -2 在lib/tools.py文件中封裝日誌記錄函數,返回logger def save_log(log_type): from conf.settings import LOGGING_DIC from logging import config, getLogger config.dictConfig(LOGGING_DIC) return getLogger(log_type) -3 在邏輯接口層中調用save_log函數返回logger,使用logger.info(msg)記錄日誌 模塊導入-避免循環導入問題 Copy# 兩種方式避免循環導入問題 - 方式1:如果只有某一個函數需要導入自定義模塊,則在函數局部作用域導入模塊 - 方式2:後一個導入者使用import導入,不要使用from ... import ... 導入 函數對象自動添加字典的bug 這個bug是在後來思考的時候發現,本項目因為採用了正確的方式避免了這個bug。具體bug參考這篇博客 Copy# 自動將功能函數添加到core.src中的func_dict字典。 # 如果將func_dict字典放在一個單獨的py文件中會方便避免這個bug # 這個bug的主要原因在於:模塊導入的先後順序和搜索模塊的順序 總結 軟體開發目錄規範 每個人創建目錄規範的樣式不盡相同。這都沒有關係,關鍵是整個項目程序組織結構清晰。 目錄規範儘可能遵循大多數人使用的方式,這樣你的代碼可讀性才會比較友好。 項目三層架構設計 三層架構設計是一種項目開發的思想方案。一旦確定了這種開發模式,編寫代碼時刻區分出不同層次的職能。 嚴格按照每個層次的職能,不同職能的代碼放在不同的層次,不要混亂,這樣管理維護起來會很方便。 有時候某個功能過於簡單,可以直接訪問數據處理層。但最好還是遵循三層架構設計,不要跨過邏輯接口層。 存數據不是目的,取才是目的 存數據不是目的,存數據時一定要考慮取數據時的方便。 一個好的數據存儲結構和方式,驗證影響取數據時功能代碼編寫額簡潔和優美。 程序 = 數據結構 + 算法。 所以,好的數據結構,導致取數據功能的難與易。 封裝代碼,儘可能重用代碼 程序中應該儘可能多的在不喪失功能清晰的情況下,儘可能多的考慮代碼的重用。 多編寫通用功能的函數工具,在程序中使用處調用之。

 

 

TTT77941YYDDEE156365GG

 

 

文章來源取自於:

 

 

 

每日頭條 https://kknews.cc/code/r64vz2o.html

 

 

如有侵權,請來信告知,我們會立刻下架。

 

 

DMCA:dmca(at)kubonews.com

 

 

聯絡我們:contact(at)kubonews.com

 


新竹電暖器安全迴路設計台中手握式促動器開關用樹脂底座型促動器桃園PCB用繼電器設計與電路設計台中加熱器用固態繼電器設計與電路設計台南掃地機符合歐盟歐規電路設計
台南HS1C-K型鑰匙互鎖型安全開關 桃園照明/整燙縫紉符合歐盟歐規電路設計 警告標籤貼紙,警告標示貼紙製作批發與設計台中福利品安全迴路設計 台中HS5系列用門把型促動器 能輕易繞送電位高雄踏墊開關設計與電路設計 台中HR1S-DMB型/DME型非接觸式安全開關用安全繼電器模組 與螺絲端子不同,不需要定期重新鎖緊台北HG1U型小型移動式人機介面 桃園電磁鎖安全門開關設計與電路設計 安全繼電器模組客製化設計的CE認證公司

 

arrow
arrow
    全站熱搜

    jyc78qd07r 發表在 痞客邦 留言(0) 人氣()