【二十五】Python全栈之路--反射_ATM项目

本文介绍了Python中的property装饰器和反射机制,以及如何应用在ATM系统中,包括用户类、卡片类和操作类的设计,展示了如何通过反射操作卡对象和模块成员。同时涵盖了用户注册、查询等核心功能和文件存储策略。
摘要由CSDN通过智能技术生成

1. property_反射

1.1 property装饰器

# ### property 
"""
可以把方法变成属性 : 可以动态的控制属性的获取,设置,删除相关操作
@property  获取属性
@方法名.setter  设置属性
@方法名.deleter 删除属性
"""

# 方法一
"""是同一个方法名"""
class MyClass():
	
	def __init__(self,name):
		self.name = name
		
	@property
	def username(self):
		return self.name
		# pass
		
	@username.setter
	def username(self,val):
		# print(val)
		self.name = val
		pass
		
	@username.deleter
	def username(self):
		# print("222")
		del self.name
		pass

obj = MyClass("小红")
# 获取值的时候自动触发@property 装饰器下的方法
res = obj.username
print(res)

# 设置值的时候自动触发@username.setter 装饰器下的方法
obj.username = "小兰"
print(obj.username)

# 删除值的时候自动触发@username.deleter 装饰器下的方法
# del obj.username
# print(obj.username)


# 方法二
class MyClass():

	def __init__(self,name):
		self.name = name
		
	# 获取数据
	def get_username(self):
		return self.name
	
	# 设置数据
	def set_username(self,val):
		self.name = val
	
	# 删除数据
	def del_username(self):
		del self.name
		
	# 参数的顺序: 获取 , 设置  , 删除
	username = property(get_username , set_username  , del_username )
		


obj = MyClass("小芳")
# 获取值的时候,执行get_username下的相关操作
print(obj.username)

# 设置值的时候,执行 set_username 下的相关操作
obj.username = "11223344"
print(obj.username)

# 删除值的时候,执行 del_username 下的相关操作
del obj.username
print(obj.username)

1.2 反射

# ### 反射
""" 通过字符串操作类对象 或者 模块中的相关成员的操作 """
"""
#hasattr() 检测对象/类是否有指定的成员
#getattr() 获取对象/类成员的值
#setattr() 设置对象/类成员的值
#delattr() 删除对象/类成员的值 
"""


# ### part1 通过字符串反射类对象中的成员
class Father():
	pass

class Mother():
	pass
	
class Children(Father,Mother):
	eye = "蓝色的"
	weight = "1吨"
	
	def eat(self):
		print("小孩下生会喝奶")
	
	def drink(self):
		print("小孩下生喜欢喝勇闯天涯...")
		
	def __la(self):
		print("小孩自动啦,无法控制")
	
obj = Children()
	
# (1)hasattr() 检测对象/类是否有指定的成员
# 对象
res = hasattr(obj,"eye")
print(res)

# 类
res = hasattr(Children,"eat123")
print(res)


# (2)getattr() 获取对象/类成员的值
# 对象
res = getattr(obj,"weight")
print(res)
# 如果获取的值不存在,可以设置第三个参数,防止报错
res = getattr(obj,"weight123","抱歉这个值不存在")
print(res)

# 类
# 通过类进行反射 (反射出来的是普通方法)
func = getattr(Children,"drink")
print(func)
func(1)
# 通过对象进行反射 (反射出来的是绑定方法)
func = getattr(obj,"drink")
print(func)
func()

# 综合案例
strvar = "eat11"
if hasattr(obj,strvar):
	func = getattr(obj,strvar)
	func()
else:
	print("抱歉,该成员不存在")


# (3) setattr() 设置对象/类成员的值
# 对象
setattr(obj,"skin","黑人")
print(obj.skin)
# 类
setattr(Children,"skin","土耳其人")
print(Children.skin)
print(obj.skin)

# (4) delattr() 删除对象/类成员的值 
# 对象
# delattr(obj,"skin")
# print(obj.skin)

# 类
# delattr(Children,"skin")
# print(Children.skin)



# ### part2 通过字符串反射模块中的成员
"""
sys.modules 返回一个系统字典,字典的键是加载的所有模块
'__main__': <module '__main__' from '/mnt/hgfs/python32_gx/day25/2.py'>
字典中的__main__这个键对应的是该文件的模块对象;
"""

def func1():
	print("我是func1方法")
def func2():
	print("我是func2方法")
def func3():
	print("我是func3方法")

import sys
print(sys.modules) # 系统字典
module = sys.modules["__main__"]
print(module)
res = getattr(module,"func1")
print(res)

# 综合案例 : (通过字符串反射模块中的成员)
while True:
	strvar = input("请输入你想要使用的功能:")
	if hasattr(module,strvar):
		func = getattr(module,strvar)
		func()
	elif strvar.upper() == "Q":
		print("再见")
		break
	else:
		print("没有该成员~!")

2. ATM需求分许

# ### 需求分析

card 卡类
卡号    密码      余额    锁定状态
cardid  password   money   islock


person 用户类
姓名   身份证号  手机号   卡对象
name   userid     phone    card

view   视图类
登录 打印欢迎界面 打印操作界面

operation 操作类
完成10个功能

main 类,统一调用分模块的功能;
开户(1)   register 
查询(2)   query          
存钱(3)   save_money
取钱(4)   get_money
转账(5)   trans_money
改密(6)   change_pwd
锁卡(7)   lock
解卡(8)   unlock       
补卡(9)   new_card
退出(0)   save


请输入管理员的账户:admin
请输入管理员密码111
*******************************************
*                                         *
*                                         *
*         Welcome To beijing Bank          *
*                                         *
*                                         *
*******************************************
*******************************************
*           开户(1)    查询(2)             *
*           存钱(3)    取钱(4)             *
*           转账(5)    改密(6)             *
*           锁卡(7)    解卡(8)             *
*           补卡(9)    退出(0)             *
*******************************************
请选择需要办理的业务

用户和卡以什么形式存储在文件中 pickle
user.txt   => {卡号:用户对象} {"555666": 用户对象}    =>  user_dict
userid.txt => {身份证:卡号}   {"111": "555666" , "222":"777888"} => user_id_dict

模块提示:

# 基本实现
取钱:卡是否存在,是否冻结,取钱金额是否正确
转账:把一个卡里的钱转到其他卡内 (卡是否存在,是否冻结,对方账户是否存在,转账的金额是否正确)
改密:(1)原密码改密  (2)身份证改密
解卡:判断卡是否存在,使用身份证解卡
锁卡:1:使用密码冻结  2:使用身份证号冻结
补卡:将旧用户的所有信息和新卡绑定(包括名字,余额等所有卡信息和用户信息,数据重新绑定)[user_id_dict]
通过身份证 => 卡号  => 用户对象 

# 类型要判断
	姓名不能为空,为中文或者字母
	密码长度6位不能空,字母数字下划线 \w (纯数字的密码不允许的)
	身份证号长度18位不能为空,正则匹配,一个身份证号只能注册一次不能重复.
	不能给自己转账

3. 项目基本版

在项目中有一个main.py(单入口模式)、还有要给package目录(里面放入的是个各种功能模块,事例中有save保存、用户注册、查询功能)
在这里插入图片描述

main.py文件:

# ### main 入口文件
from package.view import View
from package.operation import Operation

class Main():

	@staticmethod
	def run():
		
		if View.login():
			obj = Operation()
			while True:				 
				choice = input("请选择需要办理的业务:")
				if choice == "1":
					obj.register()
				elif choice == "2":
					obj.query()
				elif choice == "3":
					pass
				elif choice == "4":
					pass
				elif choice == "5":
					pass
				elif choice == "6":
					pass
				elif choice == "7":
					pass
				elif choice == "8":
					pass
				elif choice == "9":
					pass
				elif choice == "0":
					obj.save()
					break

if __name__ == "__main__":
	Main.run()
							

package目录下有card.pyoperation.pyperson.pyview.py文件,这是ATM项目的部分功能

card.py文件:

# ### card 类
class Card():
	def __init__(self,cardid,password,money):
		self.cardid = cardid
		self.password = password
		self.money = money
		# 默认卡是不锁定的 False
		self.islock = False

operation.py文件:

# ### 操作类 operation
import os
import pickle
import random
from .card import Card
from .person import Person


class Operation():

	def __init__(self):
		# 加载user.txt文件数据
		self.load_user()
		# 加载userid.txt文件数据
		self.load_userid()
		
		
	# 加载user.txt文件数据
	def load_user(self):
		if os.path.exists("user.txt"):
			with open("user.txt",mode="rb") as fp:
				self.user_dict = pickle.load(fp)
		else:
			# 设置空字典
			self.user_dict = {}
			
		print(self.user_dict)
			
	# 加载userid.txt文件数据
	def load_userid(self):
		if os.path.exists("userid.txt"):
			with open("userid.txt",mode="rb") as fp:
				self.user_id_dict = pickle.load(fp)
		else:
			# 设置空字典
			self.user_id_dict = {}
			
		print(self.user_id_dict)			
			
	# 保存退出
	def save(self):	
		# 存储user_dict 字典
		with open("user.txt",mode="wb") as fp:
			pickle.dump(self.user_dict,fp)
	
		# 存储user_id_dict 字典
		with open("userid.txt",mode="wb") as fp:
			pickle.dump(self.user_id_dict,fp)
			
	# 注册用户	
	def register(self):
		# 获取用户名
		name = input("请输入您的姓名:")
		# 获取身份证号
		userid = input("请输入您的身份证号:")
		# 获取手机号
		phone = input("请输入您的手机号:")
		# 获取密码
		password = self.get_pwd("请输入您的密码:","请确认您的密码:")
		# 获取卡号
		cardid = self.get_cardid()
		# 卡内默认余额 10元
		money = 10
		# 创建一张卡
		card = Card(cardid,password,money)
		# 创建一个用户
		user = Person(name,userid,phone,card)
		# 存储数据到 user_dict    卡号:用户对象
		self.user_dict[cardid] = user
		# 存储数据到 user_id_dict 身份证号:卡号
		self.user_id_dict[userid] = cardid
		print("恭喜{}开卡成功,您的卡号为:{},卡内余额{}元".format(name,cardid,money))
		

	# 获取密码
	def get_pwd(self,name1,name2):
		while True:
			pwd1 = input(name1)
			pwd2 = input(name2)
			if pwd1 == pwd2:
				return pwd1
			else:
				print("两次密码不一致,请重新输入")
				
	# 获取卡号
	def get_cardid(self):
		while True:
			cardid = str(random.randrange(100000,1000000))
			if cardid not in self.user_dict:
				return cardid
			
			
	def query(self):
		# 1.获取这张卡的相关信息
		card = self.get_card_info()
		if not card:
			print("抱歉,您的这张卡不存在")
		else:
			if card.islock:
				print("抱歉,您的卡已经被锁了")
			else:
				if self.check_pwd(card):
					# 显示卡内余额
					print("您的卡内余额是{}元".format(card.money))
				
	
	# 用的信息
	def get_card_info(self):
		cardid = input("请输入您的卡号:")
		if cardid not in self.user_dict:
			return False
		else:
			# 通过卡号 -> 用户对象
			user = self.user_dict[cardid]
			return user.card
			
			
	def check_pwd(self,card):
		
		times = 1
		while times <= 3:
			pwd = input("请输入您的密码")
			if pwd == card.password:
				return True
			else:
				#剩余次数 = 总次数 - 使用次数
				print("密码错误~ , 您还剩下{}次机会".format(3 - times))
				if times == 3:
					card.islock = True
					print("抱歉,密码输错三次,卡被锁定,请联系管理员.")
			
			
			times+=1
					

person.py文件:

# ### 用户类

class Person():
	def __init__(self,name,userid,phone,card):
		self.name = name
		self.userid = userid
		self.phone = phone
		# card属性中存放的是 卡对象 ;
		self.card = card

view.py文件:

# ### 视图类
import time
# 登录 打印欢迎界面 打印操作界面
class View():
	
	def login():
		name = input("请输入管理员的账户:")
		pwd = input("请输入管理员密码:")
		if name == "admin" and pwd == "111":
			# 打印欢迎界面
			View.welcome_view()
		
			# 延迟一秒
			time.sleep(1)
			
			# 打印操作界面
			View.operation_view()
			
			return True
		else:
			print("抱歉,您的用户密码有错误")
			
	@staticmethod
	def welcome_view():
		print("*******************************************")
		print("*                                         *")
		print("*                                         *")
		print("*         Welcome To OldBoy Bank          *")
		print("*                                         *")
		print("*                                         *")
		print("*******************************************")
				
	@staticmethod
	def operation_view():
		print("*******************************************")
		print("*           开户(1)    查询(2)             *")
		print("*           存钱(3)    取钱(4)             *")
		print("*           转账(5)    改密(6)             *")
		print("*           锁卡(7)    解卡(8)             *")
		print("*           补卡(9)    退出(0)             *")
		print("*******************************************")


		
if __name__ == "__main__":
	View.login()
	
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值