一、文件

1.利用文件充当数据库编写用户登录、注册功能

文件名称:userinfo.txt

基础要求:

用户注册功能>>>:文件内添加用户数据(用户名、密码等)

用户登录功能>>>:读取文件内用户数据做校验

ps:上述功能只需要实现一次就算过关(单用户) 文件内始终就一个用户信息

拔高要求:

用户可以连续注册

用户可以多账号切换登录(多用户) 文件内有多个用户信息

ps:思考多用户数据情况下如何组织文件内数据结构较为简单

提示:本质其实就是昨天作业的第二道题 只不过数据库由数据类型变成文件

!!!!!!!!!! # 先建立一个userinfo.txt,因为注册时要先参考文本文件比较是否存在,读模式如果没有文件直接报错!
while True: print("""
--------------------------
欢迎访问员工管理系统
1.注册员工
2.登录认证
q.退出系统
--------------------------
""")
choice = input('请选择功能编号>>>:').strip() if choice == '1':
print('开始注册')
username = input('请输入用户名>>>:').strip()
password = input('请输入登录密码>>>:').strip() with open(r'userinfo.txt', 'r') as f1:
for line in f1:
real_name, real_pwd = line.split('|')
if username == real_name:
print('用户名已存在')
break
else:
with open(r'userinfo.txt', 'a') as f2:
f2.write(f'{username}|{password}\n')
print('员工%s注册成功'%username) elif choice == '2':
print('请登录')
username = input('请输入用户名>>>:').strip()
password = input('请输入登录密码>>>:').strip()
with open(r'userinfo.txt', 'r') as f:
for line in f:
real_name,real_pwd = line.split('|')
if real_name == username and real_pwd.strip('\n') == password:
print('登录成功')
break
else:
print('用户名或者密码错误')
elif choice == 'q':
print('感谢使用,系统已退出')
break
else:
print('功能完善中,找不到您输入的功能编号')

二、函数

1.同上,用函数封装,然后想用的时候用

def register(username, password):
"""
用户注册功能
""" date = f'{username}|{password}\n'
with open(r'userinfo.txt', 'r', encoding='utf8') as f1:
for line in f1:
real_name, real_pwd = line.split('|')
if username == real_name:
print('该用户已存在,请重新输入')
break
else:
with open(r'userinfo.txt', 'a', encoding='utf8') as f2:
f2.write(date)
print('用户 %s 注册成功' % username) def login(username, password):
"""
用户登录功能
"""
with open(r'userinfo.txt', 'r+', encoding='utf8') as f1:
for line in f1:
real_name, real_pwd = line.split('|')
if real_name == username and real_pwd.strip('\n') == password:
print('登录成功')
return '欢迎'
else:
print('用户名或密码错误,请检查后重新输入') def del_date(username):
"""
删除某一个用户信息
:return:
"""
with open(r'userinfo.txt', 'r', encoding='utf8') as f1:
line = f1.readlines()
with open(r'userinfo.txt', 'w', encoding='utf8') as f2:
for i in line:
if '%s'% username not in i:
f2.write(i)
print('用户%s已删除' % username) def main():
while True:
start = input('''
-----------------------------
用户登录系统
1.注册
2.登录
3.删除用户
q.退出
-----------------------------
请选择您要执行的程序编码>>>:''').strip()
if start == '1':
user = input('请输入用户名:').strip()
pwd = input('请输入密码:').strip()
register(user, pwd) elif start == '2':
user = input('请输入用户名:').strip()
pwd = input('请输入密码:').strip()
login(user, pwd)
elif start == '3':
user = input('请输入要删除的用户名:').strip()
del_date(user) elif start == 'q':
print('感谢使用')
break
else:
print('没有您要执行的程序编号哦') main()

2.利用装饰器,完成用户登录校验工作

有下列用户数据

user_data = {

'1': {'name': 'jason', 'pwd': '123', 'access': ['1', '2', '3']},

'2': {'name': 'kevin', 'pwd': '321', 'access': ['1', '2']},

'3': {'name': 'oscar', 'pwd': '222', 'access': ['1']}

}

并有三个函数

def func1():

pass

def func2():

pass

def func3():

pass

要求: 调用上述三个函数的时候需要从user_data中校验用户身份是否正确

并获取当前登录用户拥有的可执行函数功能编号即键access对应的功能编号列表

func1是1、func2是2、func3是3

并且一旦用户登录成功之后后续函数的调用不再校验用户身份

请思考如何获取函数功能编号

如何校验用户身份

如何校验权限

ps: 装饰器知识

附赠: 实现上述主体功能即可

其他扩展优化功能可暂且不写

'''

1.先编写校验用户身份的装饰器

2.然后再考虑如何保存用户登录状态

3.再完善各种需求

'''

user_data = {
'1': {'name': 'jason', 'pwd': '123', 'access': ['1', '2', '3']},
# '1': {'name': 'jason', 'pwd': '123', 'access': [func1, func2, fun3]},
'2': {'name': 'kevin', 'pwd': '321', 'access': ['1', '2']},
'3': {'name': 'oscar', 'pwd': '222', 'access': ['1']}
}
"""
1.先写模板
2.再写用户校验
3.记录用户登录状态
"""
is_login = {
'login_status': False, # 记录用户是否登录
'user_access': None # 记录登录用户的权限
}
def loin_auth(func_id):
def outer(func_name):
def inner(*args, **kwargs):
# 6.先校验用户是否登录
if is_login.get('login_status'):
# 8.需要校验功能编号是否在当前登录的用户权限中
if func_id not in is_login.get('user_access'):
print(f'您没有功能编号为{func_id}的权限')
return
res = func_name(*args, **kwargs)
return res
# 1.先获取用户的编号
user_id = input('请输入您的编号>>>>:').strip()
# 2.校验用户编号是否存在
if user_id not in user_data:
print('用户编号不存在 无法完成身份校验 请走开!!!')
return
# 3.获取用户的用户名和密码
username = input('please input your username>>>:').strip()
password = input('please input your password>>>:').strip()
# 4.获取用户编号对应的真实数据进行比对
user_dict = user_data.get(user_id)
if username == user_dict.get('name') and password == user_dict.get('pwd'):
# 5.登录成功之后修改字典中登录状态
is_login['login_status'] = True
# 6.记录当前登录用户的权限编号
is_login['user_access'] = user_dict.get('access')
# 7.校验当前函数编号是否在当前用户权限列表内
if func_id in user_dict.get('access'):
res = func_name(*args, **kwargs)
return res
else:
print(f'您没有功能编号为{func_id}的权限')
else:
print('用户名和密码错误') return inner return outer @loin_auth('1')
def func1():
print('执行函数func1') @loin_auth('2')
def func2():
print('执行函数func2') @loin_auth('3')
def func3():
print('执行函数func3') func1()
func2()
func3()

三、购物车

1.购物车框架(面条版)

项目功能

    1.注册
2.登录
3.购物
4.查看购物车
5.一键清空购物车
6.结算购物车
7.充值账户金额
8.转账
q.退出

项目说明

用户数据采用json格式存储到文件目录db下 一个用户一个单独的文件
数据格式 {"name":"jason","pwd":123}
# ps:文件名可以直接用用户名便于校验
用户注册时给每个用户添加两个默认的键值对(账户余额 购物车)
{"balance":15000,"shop_car":{}}
添加购物车功能 商品列表可以自定义或者采用下列格式
good_list = [
['挂壁面',3]
['印度飞饼', 22]
['极品木瓜', 666],
['土耳其土豆', 999],
['伊拉克拌面', 1000],
['董卓戏张飞公仔', 2000],
['仿真玩偶', 10000]
]
用户可以反复添加商品,在购物车中记录数量
{'极品木瓜':[个数,单价]}
结算购物车
获取用户购物车中所有的商品计算总价并结算即可

针对添加购物车和结算只有登录的用户才可以执行

import json
import os is_login = {
'username': ''
} dir_file = os.path.dirname(__file__)
db_dir = os.path.join(dir_file, 'db')
if not os.path.exists(db_dir):
os.mkdir(db_dir) def login_auth(func_name):
def inner(*args, **kwargs):
if is_login.get('username'):
res = func_name(*args, **kwargs)
return res
else:
print('您尚未登录嘞')
choice = input("""
您可以选择注册或者登录
1.注册
2.登录
""").strip()
if choice == '1':
register()
elif choice == '2':
login()
else:
print('不要輸入其他東西啦') return inner def register():
while True:
username = input('请输入用户名>>>:').strip()
password = input('请输入密码>>>:').strip()
second_password = input('请再次输入密码>>>:').strip()
if second_password != password:
print('两次输入的密码不一致')
user_file_path = os.path.join(db_dir, f'{username}.json')
if os.path.exists(user_file_path):
print('该用户已经被注册')
continue
with open(user_file_path, 'w', encoding='utf8') as f:
user_dict = {
'username': f'{username}',
'password': f'{password}',
'balance': 15000,
'shop_car': {}
}
json.dump(user_dict, f)
print(f'用户{username}注册成功')
return def login():
while True:
username = input('请输入用户名>>>:').strip()
user_file_path = os.path.join(db_dir, f'{username}.json')
if not os.path.exists(user_file_path):
print('都没有这个用户哦,请重新输入用户名')
continue
password = input('请输入密码>>>:').strip()
with open(user_file_path, 'r', encoding='utf8') as f:
user_dict = json.load(f)
if password != user_dict.get('password'):
print('密码错误了,请重新输入')
continue
is_login['username'] = username
print(f'用户{username}登录成功')
return @login_auth
def shopping():
# 先给客户一个篮子
temp_shop_car = {}
while True:
goods_list = [
['挂壁面', 3],
['印度飞饼', 22],
['极品木瓜', 666],
['土耳其土豆', 999],
['伊拉克拌面', 1000],
['董卓戏张飞公仔', 2000],
['仿真玩偶', 10000]
]
for num, food_date in enumerate(goods_list):
print(f'编号:{num} | 商品:{food_date[0]} | 单价{food_date[1]}')
choice_num = input('请将需要购买的商品按编号加入购物车(q可以退出)').strip()
if choice_num == 'q':
# 为了保存购物车,根据用户名来保存,先搞到用户的字典
now_user_path = os.path.join(db_dir, f'{is_login.get("username")}.json')
with open(now_user_path, 'r', encoding='utf8') as f:
now_user_dict = json.load(f)
old_shop_car = now_user_dict.get('shop_car')
# 然后就是拿后面的新购物篮来比对旧购物车
for n_name, n_list in temp_shop_car.items():
if n_name in old_shop_car:
old_shop_car[n_name][0] += temp_shop_car[n_name][0]
else:
old_shop_car[n_name] = n_list
now_user_dict['shop_car'] = old_shop_car
with open(now_user_path, 'w', encoding='utf8') as f:
json.dump(now_user_dict, f, ensure_ascii=False)
print('商品都添加成功了,欢迎下次再来')
break
if not choice_num.isdigit():
print('请不要输入除数字以外的内容哦')
continue
choice_num = int(choice_num)
if choice_num not in range(len(goods_list)):
print('没有您输入的商品编号啦')
continue
target_good_list = goods_list[choice_num] # 用户选大菜单后拿出来的有商品名称和数量单价的小列表
good_nums = input(f'请输入您要添加的{target_good_list[0]}商品数量>>>:').strip()
if not good_nums.isdigit():
print('商品数量必须纯数字')
continue
good_nums = int(good_nums)
# 下面这一步骤是为了让用户反复使用添加购物车功能时候不覆写数据,而且如果选择存在,增加数量,不存在就新增选择
good_name = target_good_list[0]
if good_name in temp_shop_car:
temp_shop_car.get(good_name)[0] += good_nums
else:
temp_shop_car[good_name] = [good_nums, target_good_list[1]]
print(temp_shop_car) @login_auth
def view_cart():
# 一样,先拿到登录用户的字典
now_user_path = os.path.join(db_dir, f'{is_login.get("username")}.json')
with open(now_user_path, 'r', encoding='utf8') as f:
now_user_dict = json.load(f)
now_user_shop_car = now_user_dict.get('shop_car')
if not now_user_shop_car:
print('您的购物车空空如也啦')
print(f'尊贵的{is_login.get("username")}您的购物车信息如下')
all_price = 0
for n_name, n_list in now_user_shop_car.items(): # {'印度飞饼': [75, 22], '仿真玩偶': [11, 10000]}
total_price_each = n_list[0] * n_list[1]
print(f'商品{n_name}的数量为{n_list[0]}总价为{total_price_each}')
all_price += total_price_each print(f'尊贵的{is_login.get("username")}您的购物车总价为{all_price}')
return @login_auth
def empty_cart():
now_user_path = os.path.join(db_dir, f'{is_login.get("username")}.json')
with open(now_user_path, 'r', encoding='utf8') as f:
now_user_dict = json.load(f)
now_user_dict['shop_car'] = {}
with open(now_user_path, 'w', encoding='utf8') as f1:
json.dump(now_user_dict, f1) print(f'尊敬的{is_login.get("username")} 您的购物车清空完成啦,快去挑选心仪的商品吧')
return @login_auth
def transfer():
while True:
print('----进入转账功能页面--按(q)可以退出----')
now_user_path = os.path.join(db_dir, f'{is_login.get("username")}.json')
with open(now_user_path, 'r', encoding='utf8') as f:
now_user_dict = json.load(f)
name_tran = input('请输入您要转账的用户名>>>:').strip()
if name_tran == 'q':
break
trans_path = os.path.join(db_dir, f'{name_tran}.json')
if not os.path.exists(trans_path):
print('找不到您要转账的账号')
continue
with open(trans_path, 'r', encoding='utf8') as f:
trans_user_dict = json.load(f)
now_user_balance = int(now_user_dict.get('balance'))
trans_user_balance = int(trans_user_dict.get('balance'))
amount_choice = input('请输入您要转账金额>>>:').strip()
if not amount_choice.isdigit():
print('转账请输入大于0的整数哈,别输入其他的哦')
continue if trans_user_balance < int(amount_choice):
print('您的账户馀额不够完成转账功能哦')
continue
now_user_dict['balance'] -= int(amount_choice)
trans_user_dict['balance'] += int(amount_choice)
with open(now_user_path, 'w', encoding='utf8') as f1:
json.dump(now_user_dict, f1)
with open(trans_path, 'w', encoding='utf8') as f1:
json.dump(trans_user_dict, f1)
print(f'尊敬的{is_login.get("username")}|您本次转账{amount_choice}|卡上余额{now_user_dict.get("balance")}') @login_auth
def settle_accounts():
now_user_path = os.path.join(db_dir, f'{is_login.get("username")}.json')
with open(now_user_path, 'r', encoding='utf8') as f:
now_user_dict = json.load(f)
now_user_shopcar = now_user_dict.get('shop_car')
if not now_user_shopcar:
print('您的购物车空空如也')
return
now_user_balance = now_user_dict.get('balance')
user_shopping_money = 0
for n_list in now_user_shopcar.values():
user_shopping_money += n_list[0] * n_list[1]
if user_shopping_money > now_user_balance:
print('您的余额不足,扣款失败')
return
else:
now_user_dict['balance'] -= user_shopping_money
now_user_dict['shop_car'] = {}
with open(now_user_path, 'w', encoding='utf8') as f1:
json.dump(now_user_dict, f1)
print(f'尊敬的{is_login.get("username")}|您本次消费{user_shopping_money}|卡上余额{now_user_dict.get("balance")}欢迎下次光临哦') @login_auth
def recharge():
# 一样,先拿到登录用户的字典
now_user_path = os.path.join(db_dir, f'{is_login.get("username")}.json')
# 拿到用户的余额信息
with open(now_user_path, 'r', encoding='utf8') as f:
now_user_dict = json.load(f)
now_user_balance = now_user_dict.get('balance')
choice = input('请输入充值金额>>>:').strip()
if not choice.isdigit():
print('不能输入数字以外的东西啦')
choice = int(choice)
now_user_dict['balance'] += choice
with open(now_user_path, 'w', encoding='utf8') as f:
json.dump(now_user_dict, f)
print(f'用户{is_login.get("username")}充值{choice}成功 当前账户余额为{now_user_dict["balance"]}') choice_func_dict = {
'1': register,
'2': login,
'3': shopping,
'4': view_cart,
'5': empty_cart,
'6': settle_accounts,
'7': recharge,
'8': transfer } while True:
print("""
-------已进入购物车系统-------
1.注册
2.登录
3.购物
4.查看购物车
5.一键清空购物车
6.结算购物车
7.充值账户金额
8.转账
q.退出
---------------------------- """)
choice = input('请选择您要执行的功能编号>>>:').strip()
if choice in choice_func_dict:
choice_func_dict.get(choice)()
elif choice == 'q':
print('感谢使用')
break
else:
print('没有您要执行的功能编号啦')

四、完整三层框架购物车

bin

start.py

import os
import sys
from core import src
base_dir = os.path.dirname(os.path.dirname(__file__)) sys.path.append(base_dir) if __name__ == '__main__':
src.src_run()

conf

settings.py

import os

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

DB_PATH = os.path.join(BASE_DIR, 'db')
USER_DATE_PATH = os.path.join(DB_PATH, 'user_date')
MONEY_RATE = 0.05 GOODS_DICT_PATH = os.path.join(DB_PATH, 'goods_dict.json') 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' # 自定义文件路径
LOG_DIR = os.path.join(BASE_DIR, 'log')
if not os.path.isdir(LOG_DIR):
os.mkdir(LOG_DIR)
LOGFILE_PATH = os.path.join(LOG_DIR, 'ATM.log') # 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)传递
}, # 当键不存在的情况下 (key设为空字符串)默认都会使用该k:v配置
# '购物车记录': {
# 'handlers': ['default','console'], # 这里把上面定义的两个handler都加上,即log数据既写入文件又打印到屏幕
# 'level': 'WARNING',
# 'propagate': True, # 向上(更高level的logger)传递
# }, # 当键不存在的情况下 (key设为空字符串)默认都会使用该k:v配置
},
}

core

amdin.py

from db import db_headler
from lib import common def del_user():
from interface import admin_interface
while True:
print('---------进入了超级权限——删除用户页面--------->>>')
name_list = db_headler.back_user_name()
name_list.remove('admin')
print('---------以下是已经存在的所有用户名-----------') # 诸如[jason,kevin,oppo]之类的
for name in name_list:
print(name, end=' | ')
print('')
print('----------------------------------------------')
choice_name = input('请输入要删除的用户名(q为退出)>>>:').strip()
if choice_name == 'q':
return
elif choice_name in name_list:
flag, msg = admin_interface.del_user_interface(choice_name)
if flag:
print(msg)
continue else:
print('请不要输入无关内容~')
continue def lock_user():
from interface import admin_interface
while True:
print('---------进入了超级权限——冻结用户页面--------->>>')
name_list = db_headler.back_user_name()
name_list.remove('admin')
print('---------以下为已注册的用户以及其冻结状态(True为冻结)-----------') # 诸如[jason,kevin,oppo]之类的
for name in name_list:
print(name, end=' ==> ')
is_lock_info = db_headler.select(name)['is_locked']
print(is_lock_info, end=' | ')
print('')
print('----------------------------------------------------------')
choice_name = input('请输入要冻结的用户名(q为退出)>>>:').strip()
if choice_name == 'q':
return
elif choice_name in name_list:
flag, msg = admin_interface.lock_user_interface(choice_name)
if flag:
print(msg)
continue
print(msg)
continue
else:
print('请不要输入无关内容~') def unlock_user():
from interface import admin_interface
while True:
print('---------进入了超级权限——解冻用户页面--------->>>')
name_list = db_headler.back_user_name()
name_list.remove('admin')
print('---------以下为已注册的用户以及其冻结状态(True为冻结)-----------') # 诸如[jason,kevin,oppo]之类的
for name in name_list:
print(name, end=' ==> ')
is_lock_info = db_headler.select(name)['is_locked']
print(is_lock_info, end=' | ')
print('')
print('----------------------------------------------------------')
choice_name = input('请输入要解冻的用户名(q为退出)>>>:').strip()
if choice_name == 'q':
return
elif choice_name in name_list:
flag, msg = admin_interface.unlock_user_interface(choice_name)
if flag:
print(msg)
continue
print(msg)
continue
else:
print('请不要输入无关内容~') def change_user_balance():
from interface import admin_interface
while True:
print('---------进入了超级权限——修改用户余额页面--------->>>')
name_list = db_headler.back_user_name()
name_list.remove('admin')
print('---------以下为已注册的用户以及其余额-----------') # 诸如[jason,kevin,oppo]之类的
for name in name_list:
print(name, end='==> 余额: ')
is_lock_info = db_headler.select(name)['balance']
print(is_lock_info, end=' | ')
print('')
print('----------------------------------------------------------')
choice_name = input('请输入要修改余额的用户名(q为退出)>>>:').strip()
if choice_name == 'q':
return
if choice_name in name_list:
choice_num = input('请输入要改成的数额>>>:').strip()
flag, msg = common.get_num(choice_num)
if flag:
if msg <= 0:
print('不要输入负数啊!我的盆友')
continue
flag2, msg2 = admin_interface.change_user_balance_interface(choice_name, msg)
if flag2:
print(msg2)
continue
print(msg)
continue
else:
print('请不要输入无关内容~') def add_goods():
from interface import admin_interface
while True:
print('---------进入了超级权限——添加商城商品页面--------->>>')
goods_dict = db_headler.get_goods_dict()
a = len(goods_dict)
name = input('请输入要添加的商品名字(q可以退出)>>>:').strip()
if name == 'q':
break
price = input('请输入要添加的商品单价>>>:').strip()
flag, msg = admin_interface.add_goods_interface(a, name, price)
if flag:
print(msg) def del_goods():
from interface import admin_interface
while True:
print('---------进入了超级权限——删除商城商品页面--------->>>')
goods_dict = db_headler.get_goods_dict()
print('---------以下是已经存在的所有商品信息-----------')
for num, good_info in goods_dict.items():
print(f'商品编号:{num} |商品名称:{good_info["goods_name"]} | 商品单价:{good_info["price"]}')
name_choice = input('请输入要删除的商品编号(q可以退出)>>>:').strip()
if name_choice == 'q':
break
elif name_choice not in goods_dict:
print('请不要输入超出商品列表范围的编号哦~')
continue
flag, msg = admin_interface.del_goods_interface(name_choice)
if flag:
print(msg)
continue
print(msg) admin_dict = {
'1': del_user,
'2': lock_user,
'3': unlock_user,
'4': change_user_balance,
'5': add_goods,
'6': del_goods
} def admin_run():
while True:
print("""
----------------欢迎进入管理员系统----------------
| 1.删除用户 |
| 2.冻结用户 |
| 3.解冻用户 |
| 4.修改用户余额 |
| 5.添加商品 |
| 6.删除商品 |
-----------------------------------------------
""") admin_choice = input('请输入您要执行的功能编号(q为退出)>>>:').strip()
if admin_choice == 'q':
print('感谢您的使用,系统已退出')
break
if admin_choice in admin_dict:
admin_dict[admin_choice]()
else:
print('请不要输入无关内容~')
continue

src.py

import time

import core.admin
from lib import common is_login = {
'username': ''
} def register():
from interface import user_interface
while True:
print('---------进入了注册页面--------->>>')
username = input('请输入注册用户名(q可以退出)>>>:').strip()
if username == 'q':
break
password = input('请输入注册用户的密码>>>:').strip()
auth_password = input('请再次输入注册用户的密码>>>:').strip()
if not password == auth_password:
print('两次输入的密码不一致,请重新注册')
continue
password = common.get_hash(password)
flag, msg = user_interface.register_interface(username, password)
if flag:
print(msg)
return
print(msg)
continue def login():
from interface import user_interface
while True:
print('---------进入了登录页面--------->>>')
username = input('请输入登录用户名(q可以退出)>>>:').strip()
if username == 'q':
break
password = input('请输入用户的密码>>>:').strip()
password = common.get_hash(password)
flag, msg = user_interface.login_interface(username, password)
if flag:
print(msg)
return
print(msg)
continue @common.login_auth
def view_balance():
from interface import bank_interface
print('---------进入了查看余额页面--------->>>')
flag, msg = bank_interface.view_balance_interface(is_login['username'])
print(msg)
time.sleep(2) @common.login_auth
def withdraw():
from interface import bank_interface
while True:
print('---------进入了提现页面--------->>>')
withdraw_money = input('请输入您要提现的金额(q为退出)>>>:').strip()
if withdraw_money == 'q':
print('退出了提现页面')
break
flag, msg = common.get_num(withdraw_money)
if flag:
if msg >= 0:
flag2, msg2 = bank_interface.withdraw_interface(is_login['username'], msg)
if flag2:
print(msg2)
continue
print(msg2)
continue
else:
print('请输入大于等于0的数')
continue
print(msg) @common.login_auth
def recharge():
from interface import bank_interface
while True:
print('---------进入了充值页面--------->>>')
recharge_money = input('请输入您要充值的金额(q为退出)>>>:').strip()
if recharge_money == 'q':
print('退出了充值页面')
break
flag, msg = common.get_num(recharge_money)
if flag:
if msg >= 0:
flag2, msg2 = bank_interface.recharge_interface(is_login['username'], msg)
if flag2:
print(msg2)
continue
print(msg2)
continue
else:
print('请输入大于等于0的数')
continue
print(msg) @common.login_auth
def transfer():
from interface import bank_interface
while True:
print('---------进入了转账页面--------->>>')
transfer_name = input('请输入您要转账的用户名(q为退出)>>>:').strip()
if transfer_name == 'q':
print('退出了转账页面')
break
transfer_money = input('请输入您要转账的金额>>>:').strip()
flag, msg = common.get_num(transfer_money)
if flag:
if msg >= 0:
flag2, msg2 = bank_interface.transfer_interface(is_login['username'], transfer_name, msg)
if flag2:
print(msg2)
continue
print(msg2)
continue
else:
print('请输入大于等于0的数')
continue
print(msg) @common.login_auth
def add_shop_car():
from interface import shop_interface
from db import db_headler
while True:
goods_dict = db_headler.get_goods_dict()
print('--------------------欢迎光临硬件妙妙屋---------------------')
for num, good_info in goods_dict.items(): #good_info 是一个字典 {'goods_name': '罗技-G502', 'price': 299}
print(f'商品编号:{num} |商品名称:{good_info["goods_name"]} | 商品单价:{good_info["price"]}')
user_choice = input('请选择您要添加的商品编号(q为退出)>>>:').strip()
if user_choice == 'q':
print('退出了商城')
break
elif user_choice not in goods_dict:
print('请不要输入超出商品列表范围的编号哦~')
continue
elif not user_choice.isdigit():
print('请不要输入其他内容哦~')
continue
choice_num = input('请选择您要添加数量>>>:').strip()
if not choice_num.isdigit() and choice_num == '0':
print('请输入大于0的整数~')
continue
flag, msg = shop_interface.add_shop_car_interface(goods_dict[user_choice], int(choice_num), is_login['username'])
if flag:
print(msg)
continue
print(msg) @common.login_auth
def view_shop_car():
from interface import shop_interface
while True:
print('---------进入了查看购物车页面--------->>>')
flag, msg = shop_interface.view_shop_car_interface(is_login['username'])
if flag:
for i in msg:# 注意这里只循环了K
print(f'商品名:{i}', end='')
print(f'数量:{msg[i]["数量"]} | 该项总价: {msg[i]["总价"]} ')
wait = input('-------以上为您的购物车所有内容(q可以退出)-------')
if wait == 'q':
break
print(msg)
continue @common.login_auth
def clear_shop_car():
from interface import shop_interface
while True:
print('---------进入了清理购物车页面--------->>>')
choice = input('确定要清理购物车吗?(n为退出)y/n >>>:').strip()
if choice == 'q':
break
elif choice == 'y':
flag, msg = shop_interface.clear_shop_car_interface(is_login['username'])
if flag:
print(msg)
break
print(msg)
break
else:
print('不要输入无关内容啦')
continue @common.login_auth
def settle_shop_car():
from interface import shop_interface
while True:
print('----------进入了结算购物车页面--------->>>')
flag, msg = shop_interface.settle_shop_car_interface(is_login['username'])
if flag:
print(msg)
break
else:
print(msg)
while True:
choice = input('结算失败啦\n 1.去购物~\n 2.充值\n 3.退出\n 您的选择>>>:').strip()
if choice == '3':
return
elif choice == '1':
add_shop_car()
return
elif choice == '2':
recharge()
return
else:
print('不要输入无关内容啦')
continue @common.login_auth
def view_water_flow():
from interface import bank_interface
while True:
print('---------进入了查看流水页面--------->>>')
flag, msg = bank_interface.view_water_flow_interface(is_login['username'])
if flag:
for i in msg:
print(i)
wait = input('--------------以上为您的流水账目(q可以退出)------------')
if wait == 'q':
break
print(msg)
break @common.login_auth
def member():
from interface import user_interface
print('---------进入了会员介绍页面--------->>>')
print("""
-----------------------------------------
| 特大好消息!特大好消息! |
| 不要99998,不要9998,只要998!998! |
| 终身会员只要998! |
| 全场购物95折,提现手续费95折! |
| 购物满199元包邮顺丰到家,每月更有好礼相赠 |
| 你还在犹豫什么,快来加入会员吧! |
-----------------------------------------
""")
user_choice = input('是否要付费成为终身会员?(n可以退出) y/n >>>:')
if user_choice == 'n':
return
elif user_choice.lower() == 'y':
flag, msg = user_interface.member_interface(is_login['username'])
if flag:
print(msg)
return
while True:
next_choice = input('您的余额不足啦,是否要充值呢?(n可以退出) y/n').strip()
if next_choice == 'y':
register()
return
elif next_choice == 'n':
return
else:
print('不要输入无关内容哦~')
continue
else:
print('不要输入无关内容哦~') @common.login_auth
def admin_system():
if is_login['username'] == 'admin':
core.admin.admin_run()
else:
print('您不是管理员,无权进入管理员系统') src_dict = {
'1': register,
'2': login,
'3': view_balance,
'4': withdraw,
'5': recharge,
'6': transfer,
'7': add_shop_car,
'8': view_shop_car,
'9': clear_shop_car,
'10': settle_shop_car,
'11': view_water_flow,
'12': member,
'13': admin_system
} def src_run():
while True:
print("""
----------------欢迎进入ATM系统----------------
| 1.注册功能 |
| 2.登录功能 |
| 3.查看余额 |
| 4.提现功能 |
| 5.充值功能 |
| 6.转账功能 |
| 7.购物功能 |
| 8.查看购物车 |
| 9.清空购物车 |
| 10.结算购物车 |
| 11.查看流水 |
| 12.会员功能 |
| 13.管理员系统 |
| q.退出系统 |
--------------------------------------------
""") src_choice = input('请输入您要执行的功能编号(q为退出)>>>:').strip()
if src_choice == 'q':
print('感谢您的使用,系统已退出')
break
if src_choice in src_dict:
src_dict[src_choice]()
else:
print('请不要输入无关内容~')
continue

db

db_headler.py

import json
import os
from conf import settings def select(username):
user_path = os.path.join(settings.USER_DATE_PATH, f'{username}.json')
if not os.path.exists(user_path):
return False
else:
with open(user_path, 'r', encoding='utf8') as f:
user_dict = json.load(f)
return user_dict def save(user_dict):
username = user_dict['username']
user_path = os.path.join(settings.USER_DATE_PATH, f'{username}.json')
with open(user_path, 'w', encoding='utf8') as f:
json.dump(user_dict, f, ensure_ascii=False) def get_goods_dict():
path = settings.GOODS_DICT_PATH
with open(path, 'r', encoding='utf8') as f:
goods_dict = json.load(f)
return goods_dict def save_goods_dict(after_dict):
path = settings.GOODS_DICT_PATH
with open(path, 'w', encoding='utf8') as f:
json.dump(after_dict, f, ensure_ascii=False) def back_user_name():
user_date_path = os
list_file = os.listdir(settings.USER_DATE_PATH)
list_name = [i.split('.')[0] for i in list_file if i.endswith('.json')]
return list_name

goods_dict.json

interface

admin_interface.py

import time
import os
from lib import common
from db import db_headler
from conf import settings
logger = common.get_logger('管理员模块')
now_time = time.strftime('%Y-%m-%d--%X') def del_user_interface(username):
user_path = os.path.join(settings.USER_DATE_PATH, f'{username}.json')
os.remove(user_path)
return True, f'用户{username}删除成功!' def lock_user_interface(username):
user_dict = db_headler.select(username)
if user_dict['is_locked']: # 默认都是False
return False, f'用户{username} 已经处于冻结状态了'
user_dict['is_locked'] = True
db_headler.save(user_dict)
logger.debug(f'管理员冻结了{username}用户')
return True, f'{now_time} 用户{username} 冻结成功' def unlock_user_interface(username):
user_dict = db_headler.select(username)
if not user_dict['is_locked']:
return False, f'用户{username} 没有被冻结,无需解冻'
user_dict['is_locked'] = False
db_headler.save(user_dict)
logger.debug(f'管理员解冻了{username}用户')
return True, f'{now_time} 用户{username} 解冻成功' def change_user_balance_interface(username, num):
user_dict = db_headler.select(username)
user_dict['balance'] = num
db_headler.save(user_dict)
logger.debug(f'管理员修改了{username}用户的余额为{num}')
user_dict['water_flow'].append(f'{now_time}账户余额被管理员更改为{num}')
db_headler.save(user_dict)
return True, f'修改了{username}用户余额至{num}成功!' def add_goods_interface(a, name, price):
goods_dict = db_headler.get_goods_dict()
goods_dict[a] = {'goods_name': f'{name}', 'price': f'{price}'}
db_headler.save_goods_dict(goods_dict)
return True, f'商品添加成功!' def del_goods_interface(name):
goods_dict = db_headler.get_goods_dict()
del goods_dict[name]
db_headler.save_goods_dict(goods_dict)
return True, f'商品删除成功'

bank_interface.py

import time
from lib import common
from db import db_headler
from conf import settings logger = common.get_logger('银行模块')
now_time = time.strftime('%Y-%m-%d--%X') def view_balance_interface(username):
user_dict = db_headler.select(username)
balance = user_dict['balance']
logger.debug(f'{username}查看了自己账户余额')
return True, f'{now_time} 尊敬的{username} ,您的账户余额为{balance}' def withdraw_interface(username, money):
user_dict = db_headler.select(username)
a = user_dict['discount_rate'] # a 为用户折扣利率,代码太长了
money_after = money * (1 + settings.MONEY_RATE) * a
if user_dict['balance'] <= money_after:
logger.debug(f'{username}因余额不足提现失败')
return False, f'{now_time} 尊敬的{username},账户余额不足提现失败'
user_dict['balance'] -= money_after
user_dict['water_flow'].append(f'{now_time} 提现{money}元,手续费{money * settings.MONEY_RATE * a}元 账户余额{user_dict["balance"]}')
db_headler.save(user_dict)
logger.debug(f'{username}提现金额:{money} 手续费{money * settings.MONEY_RATE * a}')
return True, f'{now_time} 尊敬的{username},提现成功,提现金额:{money} 手续费{money * settings.MONEY_RATE * a}' def recharge_interface(username, money):
user_dict = db_headler.select(username)
user_dict['balance'] += money
user_dict['water_flow'].append(f'{now_time} 充值{money}元 账户余额{user_dict["balance"]}')
db_headler.save(user_dict)
logger.debug(f'{username}充值成功金额:{money}')
return True, f'{now_time} 尊敬的{username}充值成功,金额:{money}' def transfer_interface(username, trans_name, money):
user_dict = db_headler.select(username)
trans_name_dict = db_headler.select(trans_name)
if not trans_name_dict:
return False, f'{trans_name}用户不存在,请重新输入'
user_balance = user_dict['balance']
trans_name_balance = trans_name_dict['balance']
if user_balance <= money:
logger.debug(f'{username}因余额不足转账失败')
return False, f'{now_time} 尊敬的{username},您的余额不足以完成本次转账,请重新输入'
user_balance -= money
trans_name_balance += money
user_dict['balance'] = user_balance
trans_name_dict['balance'] = trans_name_balance
user_dict['water_flow'].append(f'{now_time} 转账给{trans_name}用户{money}元 账户余额{user_dict["balance"]}')
trans_name_dict['water_flow'].append(f'{now_time} 收到{username}用户转账的{money}元 账户余额{trans_name_dict["balance"]}')
logger.debug(f'用户{username} 向 用户{trans_name}转账{money}元')
db_headler.save(user_dict)
db_headler.save(trans_name_dict)
return True, f'{now_time} 转账成功! 用户{username} 向 用户{trans_name}转账{money}元' def view_water_flow_interface(username):
user_dict = db_headler.select(username)
if user_dict['water_flow']:
return True, user_dict['water_flow']
return False, f'{now_time}用户{username}目前没有流水记录'

shop_interface.py

import time
from lib import common
from db import db_headler
logger = common.get_logger('购物车模块')
now_time = time.strftime('%Y-%m-%d--%X') def re_goods_dict():
goods_dict = db_headler.get_goods_dict()
return goods_dict def add_shop_car_interface(good_dict, good_num, username):
total = good_dict['price'] * good_num
user_dict = db_headler.select(username)
good_name = good_dict['goods_name']
temp_shop_car = {good_name: {'数量': good_num, '总价': total}}
old_shop_car = user_dict['shop_car']
if old_shop_car == {}:
user_dict['shop_car'] = temp_shop_car
if good_name not in old_shop_car:
old_shop_car.update(temp_shop_car)
user_dict['shop_car'] = old_shop_car
else:
user_dict['shop_car'].get(good_name)['数量'] += good_num
user_dict['shop_car'].get(good_name)['总价'] += total
db_headler.save(user_dict)
db_headler.save(user_dict)
logger.info(f'{username} 添加{good_name} 件数{good_num}至购物车成功')
return True, f'{now_time} 尊敬的{username} 添加 {good_name} 件数{good_num}至购物车成功' def view_shop_car_interface(username):
user_dict = db_headler.select(username)
user_shop_car = user_dict['shop_car']
if user_shop_car == {}:
return False, f'尊敬的{username}, 您的购物车空空如也~去添加商品吧'
return True, user_shop_car def clear_shop_car_interface(username):
user_dict = db_headler.select(username)
user_dict['shop_car'] = {}
db_headler.save(user_dict)
logger.info(f'{username}清理了自己的购物车')
return True, f'{now_time} 尊敬的{username}, 您的购物车清理成功' def settle_shop_car_interface(username):
user_dict = db_headler.select(username)
user_shop_car = user_dict['shop_car']
if user_shop_car == {}:
return False, f'尊敬的{username}, 您的购物车空空如也~去添加商品吧'
all_total = 0
for num, good_info in user_shop_car.items():
total = good_info['总价']
all_total += total
user_balance = user_dict['balance']
if user_balance <= all_total:
return False, f'哎呀,尊敬的{username}您的余额不够啦,结算失败'
user_balance -= all_total
user_dict['balance'] = user_balance
user_dict['water_flow'].append(f'{now_time} 在商城消费{all_total}元')
user_dict['shop_car'] = {} # 结算完后清空购物车
db_headler.save(user_dict)
logger.info(f'用户{username} 在商城消费了{all_total}元')
return True, f'{now_time}尊敬的{username}您本次结算购物车成功,消费金额{all_total}元,期待您的下次光临'

user_interface.py

import time
from lib import common
from db import db_headler
logger = common.get_logger('用户模块')
now_time = time.strftime('%Y-%m-%d--%X') def register_interface(username, password):
user_dict = db_headler.select(username)
if user_dict:
return False, f'{username}已经注册过了,请重新注册'
if username == 'admin':
user_dict = {
'username': username,
'password': password,
'balance': 999999,
'water_flow': [],
'shop_car': {},
'is_locked': False,
'is_admin': True,
'discount_rate': 1 }
db_headler.save(user_dict)
logger.info('管理员注册成功')
return True, f'管理员{username}注册成功'
user_dict = {
'username': username,
'password': password,
'balance': 15000,
'water_flow': [],
'shop_car': {},
'is_locked': False,
'is_admin': False,
'discount_rate': 1
}
db_headler.save(user_dict)
logger.info(f'用户{username}注册成功')
return True, f'{now_time} 用户{username}注册成功' def login_interface(username, password):
from core import src
user_dict = db_headler.select(username)
if user_dict:
if user_dict['is_locked']:
return False, f'{username}已经被冻结,如有疑问可以联系管理员'
if password == user_dict['password']:
logger.info(f'用户{username}登录成功')
src.is_login['username'] = username
return True, f'{now_time} 用户{username}登录成功'
logger.info(f'用户{username}登录失败')
return False, f'密码错误,请重新登录'
return False, f'{username}用户不存在,请重新登录' def member_interface(username):
user_dict = db_headler.select(username)
user_balance = user_dict['balance']
if user_balance <= 998:
logger.info(f'{username} 尝试成为会员,但是余额不足,扣款失败')
return False
user_balance -= 998
user_dict['balance'] = user_balance
user_dict['discount_rate'] = 0.95
user_dict['water_flow'].append(f'{now_time} 扣款会员费 998 元 ')
db_headler.save(user_dict)
logger.info(f'用户{username}扣款成功,成为会员')
return True, f'{now_time}恭喜您!扣款成功,成为了终身会员!快去享受会员权益吧~'

lib

common.py

import logging
import logging.config
import os
import hashlib
from conf import settings
from core import src def get_hash(something):
h5 = hashlib.md5()
h5.update(something.encode('utf8'))
back = h5.hexdigest()
return back def login_auth(func):
def inner(*args, **kwargs):
if src.is_login['username']:
res = func(*args, **kwargs)
return res
else:
while True:
choice = input('当前使用者未登录,请选择\n 1.注册 \n 2.登录 \n 您的选择>>>:').strip()
if choice == '1':
src.register()
return
elif choice == '2':
src.login()
return
else:
print('请不要输入除1和2以外的内容哦~')
continue return inner def get_num(num):
try:
num = float(num)
except ValueError:
return False, '请输入整数或者小数,不要输入其他内容'
else:
return True, num def back_file_name():
file_name_list_path = os.listdir(settings.USER_DATE_PATH)
file_name_list = [i.split('.')[0] for i in file_name_list_path if i.endswith('.json')]
return file_name_list def get_logger(msg):
logging.config.dictConfig(settings.LOGGING_DIC) # 自动加载字典中的配置
logger1 = logging.getLogger(msg)
return logger1

log

ATM.log

readme.txt

五、面向对象——完整三层架构选课系统

python_基础_习题集(10.25更新)的更多相关文章

  1. Selenium对浏览器支持的版本【2019/10/25更新】

    最新的selenium与几种常用浏览器的版本兼容情况:(以下驱动,点击直接跳转官方下载地址) 尽量选择最新版本-1的浏览器,比如最新的是60,那就使用59.(建议Chrome更新至72+版本.Fire ...

  2. python基础_格式化输出(%用法和format用法)(转载)

    python基础_格式化输出(%用法和format用法) 目录 %用法 format用法 %用法 1.整数的输出 %o -- oct 八进制%d -- dec 十进制%x -- hex 十六进制 &g ...

  3. 背水一战 Windows 10 (25) - MVVM: 通过 x:Bind 实现 MVVM(不用 Command)

    [源码下载] 背水一战 Windows 10 (25) - MVVM: 通过 x:Bind 实现 MVVM(不用 Command) 作者:webabcd 介绍背水一战 Windows 10 之 MVV ...

  4. App Store审核指南中文版(2014.10.11更新)

    App Store审核指南中文版(2014.10.11更新) 2014-10-11 16:36 编辑: suiling 分类:AppStore研究 来源:CocoaChina  2 8657 App ...

  5. Flutter实战视频-移动电商-08.Dio基础_伪造请求头获取数据

    08.Dio基础_伪造请求头获取数据 上节课代码清楚 重新编写HomePage这个动态组件 开始写请求的方法 请求数据 .但是由于我们没加请求的头 所以没有返回数据 451就是表示请求错错误 创建请求 ...

  6. [Zlib]_[0基础]_[使用zlib库压缩文件]

    场景: 1. WIndows上没找到系统提供的win32 api来生成zip压缩文件, 有知道的大牛麻烦留个言. 2. zlib比較经常使用,编译也方便,使用它来做压缩吧. MacOSX平台默认支持z ...

  7. Android零基础入门第10节:开发IDE大升级,终于迎来了Android Studio

    原文:Android零基础入门第10节:开发IDE大升级,终于迎来了Android Studio 通过前面几期的学习,我们知道了Android的前世今生,也了解了Android的系统架构和应用组件,也 ...

  8. AndoridSQLite数据库开发基础教程(10)

    AndoridSQLite数据库开发基础教程(10) 添加触发器 触发器(TRIGGER)是由事件来触发某个操作.这些事件包括INSERT.DELETE.UPDATE和UPDATE OF.当数据库系统 ...

  9. [易学易懂系列|rustlang语言|零基础|快速入门|(25)|实战2:命令行工具minigrep(2)]

    [易学易懂系列|rustlang语言|零基础|快速入门|(25)|实战2:命令行工具minigrep(2)] 项目实战 实战2:命令行工具minigrep 我们继续开发我们的minigrep. 我们现 ...

  10. /proc/interrupts 统计2.6.38.8与3.10.25差异

    eth4进,eth5出 linux-3.10.25 67:          2          3          2          3   PCI-MSI-edge     eth468: ...

随机推荐

  1. icofx把图片转为ico图标、icofx 教程

    免费的图标编辑工具 icofx的介绍 IcoFX 是一款免费的图标编辑工具,让您轻松创建 Windows XP 和 Windows Vista 图标.在编辑区您可以轻松的预览.保存.更改您的图标.您可 ...

  2. python判断密码连续,重复,大小写、数字、符号混合密码复杂度要求

    一.python 判断密码连续,重复,大小写.数字.符号混合密码复杂度要求 1. 运行环境 python 3.6.8 2. 密码必须包含大小写.数字.特殊符号中的3种且长度为8-16位 def ver ...

  3. WAF Bypass 介绍与实战

    前言 WAF是英文"Web Application Firewall"的缩写,中文意思是"Web应用防火墙",也称为"网站应用级入侵防御系统" ...

  4. element el-table固定列凹陷问题

    1.业务背景 列表显示字段过多,最后一栏操作列加固定显示,横向添加滚动条,在自测浏览器开发者模式时,发现固定列的最后一行出现了凹陷现象,网上查阅资料大多为在更新生命周期或者页面更新操作时重载页面,这些 ...

  5. 安装kali2021.1系统

    基本安装 下载地址:Downloads | Kali Linux 去官网下载,会得到kali2021.1的镜像和哈希值 打开VMware软件,新建虚拟机........................ ...

  6. C#:开发一个winform窗体程序,实现强势股票池的数据获取。(需对接第三方接口,目前可免费使用)

    写在前面:短暂的接触过一段时间的股票市场,只能说A股真的太能杀了! 开发这个工具的初衷呢,是和几个好友在每日做"慈善"后,突发奇想:如果能实时获取当前股市里强势的股票就好了,因为这 ...

  7. JZOJ 2020.02.25【NOIP提高组】模拟A 组

    闲话 难度似乎比之前的简单了一些 但是难的题还是很难(我太菜了) 总结 针对三个题,先罗列正解所涉及的算法:字符哈希,组合数学,点分治 最后一个不会 组合数学?还好吧 字符哈希? 放在 \(T1\) ...

  8. CF1742G Orray

    题目传送门 思路 大抵算是一道位运算入门题? 首先为了使 \(b_i\) 的字典序最大,我们注意到 \(b_1=a_1\),所以 \(a_1\) 必然是序列中最大的那个数. 接下来考虑贪心,设当前已经 ...

  9. C# 时间各种格式

    1.1 取当前年月日时分秒 currentTime=System.DateTime.Now; 1.2 取当前年 int 年=currentTime.Year; 1.3 取当前月 int 月=curre ...

  10. ARC157E XXYX Binary Tree 题解

    首先,条件可以抽象为 Y 不能相连,然后: 钦定根为 Y,YX 的个数加上 \(2\): 钦定某一个叶子节点为 Y,XY 的个数加上 \(1\): 钦定某一个非叶子非根节点为 Y,YX 的个数加上 \ ...