Python函数使用实例之ATM

"""
需求分析之项目功能
    	1、登录
        2、注册
        3、查看余额
        4、转账
        5、还款
        6、取款
        7、查看流水
        8、购物
        9、查看购买商品
        
划分项目目录
    -ATM
        -bin目录:
            -src.py启动文件,整个项目的入口
        -db目录:
            -db_handler.py 查询和保存方法
            -xxx.json
            -yyy.json
        -view目录
            -main.py:视图层的逻辑
        -interface目录
            -bank.py
            -user.py
            -shopping.py
        -lib目录
            -common.py 公共方法,登录认证装饰器
        -log目录
            -日志文件放在里面
        -conf目录
            -配置文件
"""

src.py

import os
import sys

path = os.path.dirname(os.path.dirname(__file__))
sys.path.append(path)

from view import main

if __name__ == '__main__':
    main.run()

db_handler.py

from conf import settings
import json
import os


# 保存用户信息json数据
def save(user_info):
    with open('%s/%s.json' % (settings.BASE_DB, user_info['name']), 'wt', encoding='utf-8') as f:
        json.dump(user_info, f, ensure_ascii=False)
        f.flush()


# 查询用户信息json数据
def select(name):
    path = '%s/%s.json' % (settings.BASE_DB, name)
    if os.path.isfile(path):
        with open('%s/%s.json' % (settings.BASE_DB, name), 'rt', encoding='utf-8') as f:
            user_info = json.load(f)
            return user_info
    else:
        return False

mian.py

from db import db_handler
from interface import bank, user
from interface import shopping as shop
from lib import common
import time

user_login = {
    'is_login': False,
    'user': None
}


# 登录功能
def login():
    if user_login['is_login']:
        print('您已经登录了,不能注册')
        return
    print('登录功能')
    count = 0
    while True:
        name = input('请输入用户名(按q退出):')
        if name == 'q': break
        user_info = user.get_userinfo_by_name(name)
        if user_info:
            if user_info['locked'] and user_info['unlocked_time'] > time.time():
                print('您的用户已经被锁,请稍后再试')
                break
            else:
                password = input('请输入密码:')
                user_info = db_handler.select(name)
                if password == user_info['password']:
                    user.unlock_name(name)
                    print('登录成功!')
                    user_login['is_login'] = True
                    user_login['name'] = name
                    break
                else:
                    print('密码错误!')
                    count += 1
                    if count >= 3:
                        user.lock_name(name)
                        user.lock_time(name)
                        print('输入密码错误次数过多,用户已经被锁定')
                        break
        else:
            print('您还没注册呢!')


# 注册功能(注册过的用户不能注册了)
def register():
    if user_login['is_login']:
        print('您已经登录了,不能注册')
        return
    print('注册功能')
    while True:
        name = input('请输入用户名(按q退出):')
        if name == 'q': break
        if not user.db_handler.select(name):
            password = input('请输入密码:')
            re_password = input('请再次输入密码:')
            if re_password == password:
                res = user.register_interface(name, password)
                if res:
                    print('注册成功')
                    user_login['is_login'] = True
                    user_login['name'] = name
                    break
            else:
                print('两次密码不一致,请重新输入。')
        else:
            print('您已经注册过了!')


@common.login_auth
def check_balance():
    print('查询余额功能')
    balance = bank.get_balance(user_login['name'])
    print('您的余额为%s元' % balance)


@common.login_auth
def transfer():
    print('转账功能')
    while True:
        to_user = input('请输入转账给的账户:')
        if user.get_userinfo_by_name(to_user):
            money = input('请输入转账金额:')
            if bank.check_money_interface(money):
                money = float(money)
                _, msg = bank.transfer_interface(user_login['name'], to_user, money)
                print(msg)
                return
            else:
                print('请输入正确的金额')
        else:
            print('请输入正确的用户名')


@common.login_auth
def repay():
    print('还款充值功能')
    while True:
        money = input('请输入取款金额(按q退出):')
        if money == 'q': break
        if bank.check_money_interface(money):
            money = float(money)
            _, msg = bank.repay_interface(user_login['name'], money)
            print(msg)
            return
        else:
            print('请输入正确的金额!')


@common.login_auth
def withdraw():
    print('取款功能')
    while True:
        money = input('请输入取款金额(按q退出):')
        if money == 'q': break
        if bank.check_money_interface(money):
            money = float(money)
            _, msg = bank.withdraw_interface(user_login['name'], money)
            print(msg)
            break
        else:
            print('请输入正确的金额!')


@common.login_auth
def check_recorder():
    print('查询流水功能')
    recorder_list = bank.get_recorder(user_login['name'])
    for item in recorder_list:
        print(item)


@common.login_auth
def shopping():
    print('购物功能')
    '''
    0 整体放到while循环中
    1 打印出所有的商品,带编号(变量存商品,字典,列表)
        [{name:汽车,price:100},{name:苹果,price:10},{name:香蕉,price:20}]
        [[汽车,100],[苹果,10],[香蕉,20]]
    2 用户输入编号,选择要购买的商品
    3 校验输入的编号要在打印的数字范围内,输入的是否是数字
        3.1 选中的商品加入到购物车(字典),消费多少钱,余额是多少
            {汽车:{价格:10,数量:1},苹果:{价格:10,数量:1},}
            [{商品名:苹果,价格:10,数量:1},{商品名:苹果,价格:10,数量:1}]
        3.2 余额减商品价格,消费金额加上商品价格
        3.3 如果当次选择的商品在购物车中,只需要改数量即可
        3.4 如果当次选择的商品不在购物车中,向购物车中新增一条记录
    
    4 输入q,退出,询问用户是否购买加入购物车的商品
        4.1 是购买,调用购买,购买商品
        4.2 不购买,直接退出
    '''
    goods = [
        ['飞机', 20000],
        ['汽车', 10000],
        ['自行车', 2000],
        ['滑板鞋', 200]
    ]
    shopping_cart = {}
    cost_money = 0
    balance = bank.get_balance(user_login['name'])
    while True:
        for i, good in enumerate(goods):
            print('%s  商品名:%s  价格%s' % (i, good[0], good[1]))
        choice = input('请输入要购买的商品编号(一次添加一个,按q退出或购买):')
        if choice.isdigit():
            choice = int(choice)
            if choice < 0 or choice > len(goods) - 1:
                print('更多商品正在上架中')
                continue
            good_name = goods[choice][0]
            good_price = goods[choice][1]
            if balance >= good_price:
                if good_name not in shopping_cart:
                    shopping_cart[good_name] = {'price': good_price, 'count': 1}
                else:
                    shopping_cart[good_name]['count'] += 1
                cost_money += good_price
                balance -= good_price
                print('%s被加入了购物车' % good_name)
                print('目前购物车有', shopping_cart)
            else:
                print('余额不足,只剩%s元' % balance)
        elif choice == 'q':
            print('退出并购买')
            y = input('是否购买?(y/n)')
            if y == 'y':
                if cost_money > 0:
                    print('输入密码,通过了')
                    msg = shop.buy_goods_interface(user_login['name'], shopping_cart, cost_money)
                    print('购买了%s', shopping_cart)
                    print(msg)
                else:
                    print('什么都没选,你还点击购买?')
                break
            else:
                print('没钱买吗?穷鬼')
                break
        else:
            print('请输入正确的数字')


@common.login_auth
def check_shopping_cart():
    print('查询购物车功能')
    cart = shop.get_shopping_cart_interface(user_login['name'])
    print(cart)


dic = {
    '1': login,
    '2': register,
    '3': check_balance,
    '4': transfer,
    '5': repay,
    '6': withdraw,
    '7': check_recorder,
    '8': shopping,
    '9': check_shopping_cart,
}


def run():
    while True:
        print(u'''
          ------- WS Bank ---------
          \033[32;1m1.  登录
          2.  注册
          3.  查看余额
          4.  转账
          5.  还款
          6.  取款
          7.  查看流水
          8.  购物
          9.  查看购买商品
          \033[0m''')
        choice = input('请输入编号(按q退出):').strip()
        # time1 = time.time()
        # time.sleep(2)
        # time2 = time.time()
        # print(time2- time1)
        if choice == 'q': break
        if choice in dic:
            dic[choice]()
        else:
            print('请输入正确的数字编号。')

user.py

from db import db_handler
import time

def register_interface(name, password, balance=15000):
    user_info = {'name': name, 'password': password, 'balance': 15000, 'credit': 15000, 'locked': False,
                 'unlocked_time': None, 'bank_flow': [], 'shopping_cart': {}}
    db_handler.save(user_info)
    return True


def get_userinfo_by_name(name):
    user_info = db_handler.select(name)
    return user_info


# 锁定用户接口
def lock_name(name):
    user_info = db_handler.select(name)
    if user_info:
        user_info['locked'] = True
        db_handler.save(user_info)


# 锁定用户时间接口
def lock_time(name):
    user_info = db_handler.select(name)
    user_info['unlocked_time'] = time.time() + 180
    db_handler.save(user_info)


# 解锁用户接口
def unlock_name(name):
    user_info = db_handler.select(name)
    if user_info:
        user_info['locked'] = False
        db_handler.save(user_info)

bank.py

from db import db_handler
from interface import user
from lib import common
import time

logger_bank = common.load_my_logging_cfg('bank')


# 判断是否为金额接口
def check_money_interface(money):
    # 支付时,输入的金额可能是小数,也可能是整数
    s = str(money)
    if s.count('.') == 1:  # 判断小数点个数
        sl = s.split('.')  # 按照小数点进行分割
        left = sl[0]  # 小数点前面的
        right = sl[1]  # 小数点后面的
        count_right = 0
        for num in right:
            count_right += 1
        if 2 >= count_right >= 0:
            if left.startswith('-') and left.count('-') == 1 and right.isdigit():
                lleft = left.split('-')[1]  # 按照-分割,然后取负号后面的数字
                if lleft.isdigit():
                    return False
            elif left.isdigit() and right.isdigit():
                # 判断是否为正小数
                return True
        else:
            return False
    elif s.isdigit():
        s = int(s)
        if s != 0:
            return True
    return False


# 获取余额接口
def get_balance(name):
    user_info = user.get_userinfo_by_name(name)
    logger_bank.info('%s在%s查询余额' % (name, time.strftime('%F-%H:%M:%S')))
    return user_info['balance']


# 取现接口
def withdraw_interface(name, money):
    user_info = db_handler.select(name)
    if user_info['balance'] >= money * 1.05:
        user_info['balance'] -= money * 1.05
        user_info['balance'] = round(user_info['balance'], 2)
        user_info['bank_flow'].append('%s取现%s元,扣除手续费%.2f元' % (name, money, money * 0.05))
        db_handler.save(user_info)
        # 记录日志
        logger_bank.info('%s在%s取现%s元,扣除手续费%s元' % (name, time.strftime('%F-%H:%M:%S'), money, money * 0.05))
        return True, '取款成功'
    else:
        return False, '余额不足'


# 还款接口
def repay_interface(name, money):
    user_info = db_handler.select(name)
    user_info['balance'] += money
    user_info['bank_flow'].append('%s还款%s元' % (name, money))
    user_info['balance'] = round(user_info['balance'], 2)
    db_handler.save(user_info)
    logger_bank.info('%s在%s还款%s元' % (name, time.strftime('%F-%H:%M:%S'), money))
    return True, '还款成功'


# 转账接口
def transfer_interface(from_user, to_user, money):
    from_user_info = db_handler.select(from_user)
    to_user_info = db_handler.select(to_user)
    if from_user_info['balance'] >= money:
        from_user_info['balance'] -= money
        from_user_info['balance'] = round(from_user_info['balance'], 2)
        from_user_info['bank_flow'].append('%s向%s转账%s元' % (from_user, to_user, money))
        to_user_info['balance'] += money
        to_user_info['balance'] = round(to_user_info['balance'], 2)
        to_user_info['bank_flow'].append('%s向%s转账%s元' % (to_user, from_user, money))
        db_handler.save(from_user_info)
        db_handler.save(to_user_info)
        logger_bank.info('%s在%s向%s转账%s元' % (from_user, time.strftime('%F-%H:%M:%S'), to_user, money))
        return True, '转账成功'
    else:
        return False, '余额不足!'


# 查看流水接口
def get_recorder(name):
    user_info = db_handler.select(name)
    logger_bank.info('%s在%s查看了流水' % (name, time.strftime('%F-%H:%M:%S')))
    return user_info['bank_flow']


# 消费接口
def consume_interface(name, money):
    user_info = db_handler.select(name)
    user_info['balance'] -= money
    user_info['bank_flow'].append('%s购买商品%s元' % (name, money))
    db_handler.save(user_info)
    logger_bank.info('%s在%s购买商品%s元' % (name, time.strftime('%F-%H:%M:%S'), money))
    return True

shopping.py

from db import db_handler
from interface import bank


# 获取购物车接口
def get_shopping_cart_interface(name):
    user_info = db_handler.select(name)
    return user_info['shopping_cart']


# 购买商品接口
def buy_goods_interface(name, shopping_cart, money):
    user_info = db_handler.select(name)
    user_info['shopping_cart'] = shopping_cart
    db_handler.save(user_info)
    bank.consume_interface(name, money)
    return '购买成功'

common.py

from view import main

"""
logging配置
"""

import os
import logging.config
from conf import settings

# 定义三种日志输出格式 开始

standard_format = '[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]' \
                  '[%(levelname)s][%(message)s]'  # 其中name为getlogger指定的名字

simple_format = '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s'

id_simple_format = '[%(levelname)s][%(asctime)s] %(message)s'

# 定义日志输出格式 结束

logfile_dir = settings.BASE_LOG  # log文件的目录

logfile_name = 'atm.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': {},
    'handlers': {
        # 打印到终端的日志
        'console': {
            'level': 'DEBUG',
            'class': 'logging.StreamHandler',  # 打印到屏幕
            'formatter': 'simple'
        },
        # 打印到文件的日志,收集info及以上的日志
        'default': {
            'level': 'DEBUG',
            'class': 'logging.handlers.RotatingFileHandler',  # 保存到文件
            'formatter': 'standard',
            'filename': logfile_path,  # 日志文件
            'maxBytes': 1024 * 1024 * 5,  # 日志大小 5M
            'backupCount': 5,
            'encoding': 'utf-8',  # 日志文件的编码,再也不用担心中文log乱码了
        },
    },
    'loggers': {
        # logging.getLogger(__name__)拿到的logger配置
        '': {
            'handlers': ['default', 'console'],  # 这里把上面定义的两个handler都加上,即log数据既写入文件又打印到屏幕
            'level': 'DEBUG',
            'propagate': True,  # 向上(更高level的logger)传递
        },
    },
}


def load_my_logging_cfg(name):
    logging.config.dictConfig(LOGGING_DIC)  # 导入上面定义的logging配置
    logger = logging.getLogger(name)  # 生成一个log实例
    # logger.info('It works!')  # 记录该文件的运行状态
    return logger


# 登录认证装饰器
def login_auth(func):
    def inner(*args, **kwargs):
        if main.user_login['is_login']:
            res = func(*args, **kwargs)
            return res
        else:
            main.login()

    return inner

settings.py

import os

BASE_DIR = os.path.dirname(os.path.dirname(__file__))

BASE_DB = os.path.join(BASE_DIR, 'db')

BASE_LOG = os.path.join(BASE_DIR, 'log')

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值