Python函数实战之ATM与购物车系统
一、Python函数实战之ATM与购物车系统
- 项目需求:
FUNC_MSG = {
'0': '注销',
'1': '登录',
'2': '注册',
'3': '查看余额',
'4': '转账',
'5': '还款',
'6': '取款',
'7': '查看流水',
'8': '购物',
'9': '购物车',
'q': '退出'
} - 项目各模块实现
- 配置文件(conf/setting.py)
点击查看代码
import os
import logging.config #用于配置Python的日志系统
#(功能代码映射到中文描述的字典)
FUNC_MSG = {
'0': '注销',
'1': '登录',
'2': '注册',
'3': '查看余额',
'4': '转账',
'5': '还款',
'6': '取款',
'7': '查看流水',
'8': '购物',
'9': '购物车',
'q': '退出'
}
# db/log文件路径
ATM_PATH = os.path.dirname(os.path.dirname(__file__)) #当前文件路径
DB_PATH = os.path.join(ATM_PATH, 'db') #数据库目录
LOG_PATH = os.path.join(ATM_PATH, 'log') #日志目录
GOODS_INFO_PATH = os.path.join(DB_PATH, 'goods_info.xlsx') #商品信息Excel文件路径
# logging配置
"""
%(asctime)s:时间
%(levelname)s:日志级别
%(message)s:日志消息
%(filename)s:文件名
%(lineno)d:行号
"""
# 定义三种日志输出格式
standard_format = '[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]' \
'[%(levelname)s][%(message)s]' # 其中name为getLogger()指定的名字;lineno为调用日志输出函数的语句所在的代码行
simple_format = '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s'
id_simple_format = '[%(levelname)s][%(asctime)s] %(message)s'
# 定义日志输出格式 结束
# 日志目录设置(确保日志目录存在,不存在则创建。)
logfile_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # log文件的目录,需要自定义文件路径 # atm
logfile_dir = os.path.join(logfile_dir, 'log')
logfile_name = 'log.log'
if not os.path.isdir(logfile_dir):
os.mkdir(logfile_dir)
# log文件的全路径
logfile_path = os.path.join(logfile_dir, logfile_name)
# log配置字典
LOGGING_DIC = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'standard': {
'format': standard_format
},
'simple': {
'format': simple_format
},
},
'filters': {}, # filter可以不定义
'handlers': {
# 输出到控制台
'console': {
'level': 'INFO',
'class': 'logging.StreamHandler', # 打印到屏幕
'formatter': 'simple'
},
# 输出到文件(打印到文件的日志,收集info及以上的日志)
'default': {
'level': 'INFO',
'class': 'logging.handlers.RotatingFileHandler', # 保存到文件
'formatter': 'standard',
'filename': logfile_path, # 日志文件
'maxBytes': 1024 * 1024 * 5, # 日志大小 5M (*****)
'backupCount': 5,
'encoding': 'utf8', # 日志文件的编码,再也不用担心中文log乱码了
},
},
'loggers': {
# logging.getLogger(__name__)拿到的logger配置。
# 如果''设置为固定值logger1,则下次导入必须设置成logging.getLogger('logger1')
'':{
# 这里把上面定义的两个handler都加上,即log数据既写入文件又打印到屏幕
'handlers': ['default', 'console'],
'level': 'DEBUG',
'propagate': False, # 向上(更高level的logger)传递
},
},
}
- 核心代码模块(core/src.py)
点击查看代码
from lib import common
from interface import user, bank, store
logger = common.load_logging_config('user') # 加载日志配置,指定日志类别为user
user_auth = {'username': None} # 初始化用户认证字典,记录当前登录用户
username = user_auth['username']
# 登录验证装饰器,确保只有登录用户能访问
@common.login_auth
def logout():
username = None
user_auth['username'] = None
print(f'{username}已经注销')
logger.info(f'{username}已经注销') # 打印注销信息并记录日志
def login():
print('欢迎来到登录功能')
# 声明修改全局变量
global username
count = 0
while count < 3:
login_username, pwd = common.input_username_pwd()
# 登录是否成功(布尔值),登录结果消息(字符串),错误级别
flag, msg, level = user.login_interface(login_username, pwd)
print(msg)
if flag:
user_auth['username'] = login_username
username = login_username
logger.info(f'{username}登录成功')
break
if level in [2, 3]:
user.locked_interface(login_username)
print('你的账户已被锁定!')
break
count += 1
def register():
print('欢迎来到注册界面')
count = 0
while count < 3:
username, pwd = common.input_username_pwd()
flag, msg = user.register_interface(username, pwd)
# 判断是否注册成功
print(msg)
if flag:
logger.info(f'{username}注册成功')
break
count += 1
@common.login_auth
def check_extra():
print('欢迎来到查看余额界面')
extra = bank.check_extra_interface(username)
print(f'你的余额为{extra}')
logger.info(f'{username}查看余额,余额为{extra}')
return extra
@common.login_auth
def transfer():
print('欢迎来到转账功能')
from_username = username
to_username = input('请输入需要转账的用户:')
flag = common.check_user(to_username)
if flag:
money = int(input('请输入需要转账的金额:'))
flag, msg = bank.transfer_interface(from_username, to_username, money)
print(msg)
if flag:
logger.info(f'{from_username}向{to_username}转了{money}')
print(f'{from_username}向{to_username}转了{money}')
else:
print('用户不存在')
@common.login_auth
def repay():
print('欢迎来到还款功能')
flag, msg = bank.repay_interface(username)
print(msg)
logger.info(f'{username}{msg}')
@common.login_auth
def withdraw():
print('欢迎来到取款功能')
money = int(input('取现多少钱:').strip())
flag, msg = bank.withdraw_interface(username, money)
print(msg)
if flag:
logger.info(f'{username}{msg}')
return
@common.login_auth
def history():
print('欢迎来到银行流水查看功能')
s = bank.history_interface(username)
print(f'流水为:\n{s}')
logger.info(f'{username}查看了流水')
@common.login_auth
def shopping():
print('欢迎来到购物功能')
# print(f"当前用户状态: {user_auth}")
# print(f"全局username: {username}")
msg = store.shopping_interface()
print(f'{username}{msg}')
logger.info(f'{username}{msg}')
@common.login_auth
def shopping_car():
print('欢迎来到购物车功能')
shopping_car_dict = store.shopping_car_dict
flag, msg = store.shopping_car_interface(shopping_car_dict, username)
print(msg)
if flag:
logger.info(f'{username}{msg}')
def run():
FUNC_DICT = {
'0': logout,
'1': login,
'2': register,
'3': check_extra,
'4': transfer,
'5': repay,
'6': withdraw,
'7': history,
'8': shopping,
'9': shopping_car,
}
from conf.settings import FUNC_MSG
"""运行函数,进行功能选择"""
while True:
for k, v in FUNC_MSG.items():
print(f'{k}: {v}')
func_choice = input('请选择你需要的功能,输入q退出:').strip()
# 退出判断
if func_choice == 'q':
break
# 获取功能
func = FUNC_DICT.get(func_choice)
if not func:
print('沙雕,功能不存在')
continue
func()
if __name__ == '__main__':
run()
- 数据管理模块(db/db_handler.py)
点击查看代码
import os
import json
import numpy as np
import pandas as pd
from conf import settings
def save_json(username: str, content: dict):
"""保存为json文件"""
user_path = os.path.join(settings.DB_PATH, f'{username}.json') # 安全拼接路径
with open(user_path, 'w', encoding='utf8') as fw:
json.dump(content, fw) # 将字典写入JSON文件
# 表示返回字典
def read_json(username: str) -> dict:
"""读取json文件"""
user_path = os.path.join(settings.DB_PATH, f'{username}.json')
with open(user_path, 'r', encoding='utf8') as fr:
data = json.load(fr) # 从JSON文件读取数据为字典
return data
def save_excel(df, filename):
"""保存excel"""
df.to_excel(filename) # df(Pandas DataFrame对象),DataFrame保存为Excel
def read_excel(filename):
"""读取excel"""
df = pd.read_excel(filename, index_col=0, header=0)
return df
if __name__ == '__main__':
# 测试JSON功能
save_json('nick', {'name': 'nick'})
data = read_json('nick')
print(data)
# 测试Excel功能
arr = np.random.rand(3, 4) # 创建3x4随机数组
df = pd.DataFrame(arr) # 转为DataFrame
save_excel(df,'goods_info.xlsx') # 应添加文件名参数
# 读取商品信息
data = read_excel(settings.GOODS_INFO_PATH)
print(data)
- 用户,银行,购物三方接口模块(interface/user.py,bank.py,store.py)
user.py
点击查看代码
from db import db_handler
def register_interface(username, pwd):
"""注册接口"""
flag = common.check_user(username)
if flag:
return False, '用户已存在'
else:
content = {'username': username, 'pwd': pwd, 'extra': 15000, 'locked': 0}
db_handler.save_json(username, content)
return True, '用户注册成功'
def login_interface(username, pwd):
# 判断用户是否存在
flag = common.check_user(username)
if not flag:
return False, '用户不存在', 1
# 判断用户是否锁定
data = db_handler.read_json(username)
if data['locked']:
return False, '用户已经锁定,去解锁', 2
if pwd == data['pwd']:
return True, '登录成功', 0
return False, '密码错误', 3
def locked_interface(username):
"""输入错误密码就锁住"""
flag = common.check_user(username)
data = db_handler.read_json(username)
data['locked'] = 1
db_handler.save_json(username, data)
bank.py
点击查看代码
import os
from conf import settings
from db import db_handler
def check_extra_interface(username):
"""检查余额接口"""
data = db_handler.read_json(username)
return data['extra']
def transfer_interface(from_username,to_username,money):
from_username_data = db_handler.read_json(from_username)
to_username_data = db_handler.read_json(to_username)
if from_username_data['extra'] > money:
to_username_data['extra'] += money
from_username_data['extra'] -= money
db_handler.save_json(from_username, from_username_data)
db_handler.save_json(to_username, to_username_data)
return True, '转账成功'
return False,'转账失败'
def repay_interface(username):
username_data = db_handler.read_json(username)
extra = username_data['extra']
if extra >= 15000:
return True, '无需还款'
else:
username_data['extra'] = 15000
db_handler.save_json(username, username_data)
return True, f'还款{(15000 - extra)*1.005}成功'
def withdraw_interface(username,money):
username_data = db_handler.read_json(username)
if username_data['extra'] > money:
username_data['extra'] -= money
db_handler.save_json(username, username_data)
return True,f'取现{money}成功'
return False,'余额不足'
def history_interface(username):
filename = os.path.join(settings.LOG_PATH,'log.log')
with open(filename,'r',encoding='utf8') as fr:
s = ''
for line in fr:
if line.split('[')[-1].startswith(username):
s += line
return s
store.py
点击查看代码
from db import db_handler
from conf import settings
from lib import common
shopping_car_dict = dict()
def read_goods_interface():
df = db_handler.read_excel(settings.GOODS_INFO_PATH)
return df
df = read_goods_interface()
def shopping_interface():
while True:
print(df)
common.goods_visualize(df)
# 打印商品信息
goods = df.columns
goods_choice = input('请选择需要的商品,输入q退出:').strip()
if goods_choice == 'q':
break
if goods_choice in goods:
count_choice = input('请输入需要购买商品数量,输入q退出').strip()
if count_choice == 'q':
break
count_choice = int(count_choice)
if int(df.loc['amount', goods_choice]) < count_choice:
print('擦,库存不足')
continue
else:
goods_price = int(df.loc['price', goods_choice])
if shopping_car_dict.get(goods_choice):
shopping_car_dict[goods_choice] += (count_choice * goods_price)
else:
shopping_car_dict[goods_choice] += (count_choice * goods_price)
print(f'已经把{goods_choice}*{count_choice}加入购物车')
df.loc['amount', goods_choice] -= count_choice
else:
print('把眼睛捡起来!')
return f'已加入购物车{shopping_car_dict}'
def shopping_car_interface(shopping_car_dict, username):
goods_price = sum(shopping_car_dict.values())
username_data = db_handler.read_json(username)
if username_data['extra'] >= goods_price:
username_data['extra'] -= goods_price
username_data.update(shopping_car_dict)
db_handler.save_json(username, username_data)
new_shopping_car_dict = shopping_car_dict.copy()
shopping_car_dict.clear()
# 保存为excel文件
db_handler.save_excel(df, settings.GOODS_INFO_PATH)
return True, f'购物成功{new_shopping_car_dict}'
else:
shopping_car_dict.clear()
return False, '穷逼也购物'
if __name__ == '__main__':
read_goods_interface()
- 公共功能模块(lib/common.py)
点击查看代码
import os
import hashlib
import logging # 密码加密
import logging.config
from conf import settings
from interface import store
def login_auth(func):
from core import src
def wrapper(*args, **kwargs):
# 判断是否登录
if not src.user_auth.get('username'): # 检查登录状态
src.login() # 未登录则跳转登录
res = func(*args, **kwargs)
return res
res = func(*args, **kwargs) # 已登录直接执行函数
return res
return wrapper
def load_logging_config(name):
logging.config.dictConfig(settings.LOGGING_DIC) # 加载配置字典
logger = logging.getLogger(name) # 创建指定名称的日志记录器
return logger
def check_user(username):
"""注册接口"""
username_filename = os.path.join(settings.DB_PATH, f'{username}.json')
if os.path.exists(username_filename):
return True
return None
def input_username_pwd():
username = input('请输入你的用户名:').strip()
pwd = input('请输入你的密码:').strip()
# 密码加密
m = hashlib.md5() # 创建MD5哈希对象
m.update(pwd.encode('utf-8')) # 编码后更新哈希
pwd = m.hexdigest() # 获取十六进制哈希值
return username, pwd
def goods_visualize(df):
# 可写可不写
"""数据可视化"""
import matplotlib.pyplot as plt
from matplotlib.font_manager import FontProperties
font = FontProperties(fname='')
# 1. 准备数据
goods_columns = df.columns.to_list() # 获取商品名称列表
goods_price = df.loc['price', :].to_list()
price_index = list(range(len(goods_price)))
goods_amount = df.loc['amount', :].to_list()
amount_index = list(range(len(goods_amount)))
# 2. 创建图形
fig = plt.figure()
ax1 = fig.add_subplot(121)
# 3. 绘制价格条形图
ax1.bar(price_index, goods_price, color='yellow')
ax1.set_title('价格表', fontproperties=font)
# 4. 设置X轴标签
plt.xticks(amount_index, goods_columns, fontproperties=font, rotation=45)
for i in amount_index:
# 5. 添加数据标签
plt.text(amount_index[i], goods_price[i], s=goods_price[i])
# 同理绘制数量图...
ax2 = fig.add_subplot(122)
ax2.bar(price_index, goods_amount, color='green')
ax2.set_title('数量表', fontproperties=font)
plt.xticks(price_index, goods_columns, fontproperties=font, rotation=45)
for i in amount_index:
plt.text(amount_index[i], goods_price[i], s=goods_price[i])
plt.suptitle('商品信息表', fontproperties=font, fontsize=20, weight='bold')
plt.show()
if __name__ == '__main__':
# res = check_user('nick')
# print(res)
goods_visualize() # 模块直接运行时测试可视化功能
Python函数实战之ATM与购物车系统的更多相关文章
- Python常用模块实战之ATM和购物车系统再升级
目录 一.项目地址 二.功能需求 一.项目地址 https://github.com/nickchen121/atm 二.功能需求 FUNC_MSG = { '0': '注销', '1': '登录', ...
- 函数基础实战之ATM和购物车系统
username_list = [] prize_dict = { '0': "芭比娃娃", '1': "变形金刚", '2': "psp游戏机&qu ...
- 模块基础实战之ATM和购物车系统分文件处理
目录 一.项目地址 二.功能需求 一.项目地址 https://github.com/nickchen121/atm 二.功能需求 FUNC_MSG = { '0': '注销', '1': '登录', ...
- 函数高级实战之ATM和购物车系统升级
一.项目 二.项目地址 https://github.com/nickchen121/atm 三.功能需求 FUNC_MSG = { '0': '注销', '1': '登录', '2': '注册', ...
- Python - 函数实战
前言 参考的是慕课网提供的实战,自己编码 http://www.imooc.com/wiki/pythonlesson1/function2.html 什么是模块化程序设计 在进行程序设计时将一个大程 ...
- Python学习--------------Atm+购物车系统
一.程序需求 模拟实现一个ATM + 购物商城程序: 1.额度 15000或自定义 2.实现购物商城,买东西加入 购物车,调用信用卡接口结账 3.可以提现,手续费5% 4.每月22号出账单,每月10号 ...
- python实现简单购物车系统(练习)
#!Anaconda/anaconda/python #coding: utf-8 #列表练习,实现简单购物车系统 product_lists = [('iphone',5000), ('comput ...
- ATM系统和购物车系统 不需要文件支撑
目录 ATM系统 购物车系统 ATM系统 #coding=utf8 #Version:python 3.6.4 #Tools:Python 2019.9.7 _data_ = '2019/9/7/01 ...
- python函数版ATM
最近系统的学习python函数知识点,感觉在面向对象之前,函数的功能确实强大. 最近使用函数写了ATM项目,虽然需求简单但也有很多知识点需要注意,这个项目把python基础的很多知识点都用上了. 前前 ...
- Python基础入门-函数实战登录功能
''' 函数实战: .加法计算器 .过滤器 .登录功能实战 ''' def add(a,b): return a+b def login_order(): return 'asdfasdfdasfad ...
随机推荐
- 第1讲、#PyTorch教学环境搭建与Tensor基础操作详解
引言 PyTorch是当前深度学习领域最流行的框架之一,因其动态计算图和直观的API而备受开发者青睐.本文将从零开始介绍PyTorch的环境搭建与基础操作,适合各种平台的用户和深度学习初学者. 1. ...
- Spring Boot MyBatis使用type-aliases-package自定义类别名
摘要:介绍MyBatis 中 type-aliases-package 属性的作用.在Spring Boot项目中,使用属性type-aliases-package为MyBatis引用的实体类自定义别 ...
- 玩客云 OEC/OECT 笔记(2) 运行RKNN程序
目录 玩客云 OEC/OECT 笔记(1) 拆机刷入Armbian固件 玩客云 OEC/OECT 笔记(2) 运行RKNN程序 RKNN OEC/OEC-Turbo 使用的芯片是 RK3566/RK3 ...
- Java代码审计SpEL表达式注入
SpEL表达式概念 Spring Expression Language(SpEL) 是 Spring Framework 提供的一种功能强大的表达式语言,全称为 Spring Expression ...
- AI 赋能编程,Coding新范式
我们是袋鼠云数栈 UED 团队,致力于打造优秀的一站式数据中台产品.我们始终保持工匠精神,探索前端道路,为社区积累并传播经验价值. 本文作者:佳岚 前言 AI 的大趋势: 24.25 年是 AI 应用 ...
- Jenkinsfile_定义全局全量
一.通过def定义全局变量 注意:首行def定义的变量不能使用=赋值. def var pipeline { agent any stages { stage("定义var") { ...
- C#实现语音预处理:降噪、静音检测、自动增益(附Demo源码)
无论是在音视频录制系统,还是音视频通话系统.或视频会议系统中,对从麦克风采集到的说话的声音数据进行预处理,都是是非常必要的. 语音数据预处理主要包括:降噪(Noise Reduction).静音检 ...
- 如何最大化客户生命周期价值?APMDR 模型在袋鼠云的落地实践
相信大家都认可一个观点:不论是 To B 还是 To C,用户是企业的核心资源,是互联网产品中最重要的价值之一.因此,深入挖掘用户价值成为现在大部分企业运营的关键. 之前我们为大家介绍过如何利用 RF ...
- 开源公开课丨ChunJun数据传输模块介绍
一.直播介绍 之前的内容,我们为大家分享了ChunJun数据还原的DDL模块,以及ChunJun同步Hive事务表,本期我们为大家分享ChunJun数据传输模块介绍. 本次直播我们将从ChunJun数 ...
- Blazor学习之旅(5)数据绑定
大家好,我是Edison. 本篇,我们来了解下在Blazor中数据是如何绑定的. 关于数据绑定 如果希望 HTML 元素显示值,可以编写代码来更改显示内容.如果值发生更改,则需要编写额外的代码以更新显 ...