上期作业总结:
1、使用字典表示用户对象,例如:[{‘name’:'zhangsan','pwd':'123456',hasLogin:false}],将字典放入list中来表示数据库,请完成用户 注册、登录功能用户信息。
(1)注册
(2)登录
(3)查看
(4) 退出登录
#info以存储字典的列表的数据结构表示已有的账户信息
info = [{'name':'zhangsan','pwd':'123456','hasLogin':False},
{'name':'lisi','pwd':'123456','hasLogin':False},
{'name':'wangwu','pwd':'123456','hasLogin':False},
]
#以下三个函数用于对info的增、查、改
def get_info(n = "*",f = '*'):
"""
查看某一个用户的某个信息
:param n: 用户姓名,未指明则打印全部信息
:param f: info该用户某一个value,未指明则全输出
:return: 'Print' or 'error' or value or dict
"""
if n == '*':
for x in info:
print(x)
return 'Print'
for x in info:
if n == x['name']:
if f == '*':
return x
return x[f]
return 'error'
def set_info(n,p):
"""
向info插入一个字典
:param n: 该字典‘name’的value
:param p: 该字典‘pwd’的value
:return: ‘ok’
"""
new_info = {'name':n,'pwd':p,'hasLogin':False}
info.append(new_info)
return 'ok'
def Refresh(n,s):
"""
刷新登陆状态
:param n:账户姓名
:param s: 刷新的登陆状态,True,False
:return:‘ok’
"""
for x in info:
if n == x["name"]:
x['hasLogin'] = s
return "ok"
#以下两个函数用于实现登陆功能
def chack_login():
"""
检查登陆信息是否正确
:return: '0',name
"""
name = input("请输入名字:(输入'0'返回上一菜单)")
if name == '0':
return '0'
if get_info(name, 'pwd') == 'error':
print("无效的名字,请重试")
return chack_login()
pwd = input("请输入密码:")
if pwd != get_info(name, 'pwd'):
print("密码错误,请重试")
return chack_login()
else:
print("密码正确")
return name
def login_in():
"""
该函数实现登陆功能
:return: 'exit' or login_name
"""
login_name = chack_login()
if login_name == '0':
return 'exit'
else:
Refresh(login_name, True)
return login_name
#以下函数用于实现查看信息界面功能
def menu_info(account_info):
"""
查看信息界面
:param account_info:账户名称
:return: 'exit'
"""
while True :
print("您现在登陆的账户为%s" % (account_info))
print("请选择接下来要查看的信息:")
select = input("1.查看当前用户信息\n 2.查看所有用户信息\n 3.退出登陆")
select = int(select)
if select == 1:
print(get_info(account_info))
elif select == 2:
get_info()
elif select == 3:
Refresh(account_info, False)
return 'exit'
else:
print('您输入了无效的操作')
#以下三个函数与注册功能相关
def get_username():
"""
检查注册的用户名是否合法
:return: '0' or new_name
"""
user_name = input("请输入要创建的账户名:(输入'0'返回上一菜单)\n (要求:长度应在3到12位)")
if user_name == '0':
return '0'
if len(user_name) < 3 or len(user_name) >12:
print("用户名长度不合法")
return get_username()
if get_info(user_name) == 'error':
return user_name
else:
print("该账户已存在")
return get_username()
def get_pwd():
"""
检查注册的密码是否合法
:return: user_pwd
"""
user_pwd = input("请输入创建账户的密码:(要求:长度至少6位,但不超过20位)")
if len(user_pwd) < 6 or len(user_pwd) >20:
print("密码长度不合法")
return get_pwd()
else:
return user_pwd
def register():
"""
该函数实现注册界面的相关操作
:return:'exit'
"""
new_name = get_username()
if new_name == '0':
return 'exit'
else:
new_pwd = get_pwd()
if set_info(new_name, new_pwd) == 'ok':
print("恭喜你!注册成功。")
return 'exit'
else:
print("出现了系统错误,写入函数返回值出错")
return 'exit'
#以下函数用于实现主菜单功能
def menu_start():
"""
实现初始菜单的功能
:return: 'exit'
"""
while True:
select = input("请选择要进行的操作:\n (1)登陆\n (2)注册\n (3)退出\n")
select = int(select)
if select == 1:
result = login_in()
if result == 'exit':
continue
else:
menu_info(result)
elif select == 2:
register()
elif select == 3:
break
else:
print('无效操作,请重试')
return 'exit'
#主函数部分:
if menu_start() == 'exit':
print('退出成功')
2、模拟用户下单过程,当用户买的物品超过3件时,给与2折优惠(优先级较高)。当用户总价超过100元给与3折优惠。(高阶函数)[{“pname”:"","price":"","number":12}]
# -*- coding: utf-8 -*-
# @Time : 19-5-24 上午10:27
# @Author : Jingtao Yu
# @Email : 2463038861@qq.com
# @File : test4.5.py
# @Software: PyCharm
order = [{'pname':'note','price':8,'number':1},
{'pname':'apple','price':2,'number':5},
{'pname':'computer','price':4000,'number':1}]
def discount1(price):
"""
打二折
:param price:总价
:return: 折扣后价格
"""
return price * 0.2
def discount2(price):
"""
打三折
:param price:总价
:return: 折扣后价格
"""
return price * 0.3
def calulate(price,strategy):
"""
根据不同的策略进行不同的折扣计算
:param price: 总价
:param strategy: 策略
:return: strategy(price)
"""
if strategy == None:
return price
return strategy(price)
def discount(orders):
"""
根据优惠政策给予相应折扣后的价格
:param order: 订单列表
:return: 折扣后的价格
"""
pnum = sum([item['number'] for item in orders])
pprice = sum([item['price']*item['number'] for item in orders])
strategy = None
if pnum >= 3:
strategy = discount1
elif pprice >= 1000:
strategy = discount2
return calulate(pprice,strategy)
print('折扣后,你要付的金额为:',end = '')
print(discount(order))
面向对象
面向对象是一种编写代码的思维方式:程序是由什么构成的
- 类
- 类:其实是一种抽象。
- User类:把用户相关信息抽象到一起。
- 函数命名用下划线表示法,类名用驼峰结构,并把首字母大写。
- 一般来说,类由属性和(方法)行为组成,属性表示了这个类的特点,(方法)行为规定了这个类的功能。
- 程序(类) = 数据结构(属性) + 算法(方法、行为)
- 函数定义在类里的时候,成为方法。
- 类->实例:实例是类的具体化。
class Cat:
#构造方法,该方法会在创建对象(实例)的时候,自动调用
#分配内存:一般不考虑
#初始化值
def __init__(self,color,name):
self.color = color
self.name = name
# self指的是:当前对象(当前方法的调用者)
def catch_rat(self):
print(self.name + "抓到了老鼠")
#创建一个实例
tom = Cat('Blue','Tom')
tom.catch_rat()
#私有属性
print(tom.name)
tom.name = 'Garfield'
print(tom.name)
实例化对象的过程:1,分配内存出来(方法:new) 2,初始化值(方法:init)
- 私有属性
属性私有化:
1,两个下划线开头
2,自行约定,单下划线开头
- 双下划线为什么能够隐藏变量?
通过duct可查到,里面装的实例的所有属性。双下划线开头的属性,会被名称转换:_类名+属性名
- 语法糖
class Student:
"""
学生类
"""
def __init__(self,name,age):
self.__name = name
self.__age = age
def set_name(self,name):
if not len(name) < 3:
self.__name = name
def get_name(self):
return self.__name
#语法糖:简化了调用
@property
def age(self):
print("年龄:",end = '')
return self.__age
@age.setter
def age(self,age):
if age > 0 and age < 100:
self.__age = age
s = Student("zhangsan",20)
#提供了get、set方法
print(s.get_name())
s.set_name("lisi")
print(s.get_name())
#语法糖,让调用类方法的更简单、方便
s.age = 50
print(s.age)
类本身也是对象
类的所有属性存在一个字典里
class User:
#在类里直接定义的属性,称为类属性,类属性由所有对象共享
num = 0
def __init__(self,name):
# self.属性名:实例属性
self.name = name
User.num += 1
#使用print(对象)时,后自动调用该函数
def __str__(self):
str = ''
return str
def print_name(self):
print(self.name,User.num)
语法糖: @classmethod, @staticmethod
#定义一个类方法,类和实例皆可调用,建议通过类名来调用,该方法必须有一个类型参数“cls”
@classmethod
def create_user(cls,name,age):
#输出了该类的类型
print(cls)
user = cls(name)
user.age = age
return user
#静态方法:效果与普通函数类似,通过类名来访问(工具类),调用方式同类方法
@staticmethod
def sum(a,b):
return a + b
u = User("zs")
u.print_name()
u1 = User("ls")
u1.print_name()
User.num += 1
u1.print_name()
u2 = User.create_user('ZS',20)
print(u2.age)
print(u2.name)
print(User.sum(2,3))
案例
模拟一个游戏,有一个怪兽(Monster),还有一个玩家(Hero)
import random as rn
class Sprite:
def __init__(self,name):
self.blood = 100
self.power = 12
self.name = name
def attack(self,Enemy):
minus = rn.randrange(self.power - 5,self.power + 5)
if Enemy.has_living():
Enemy.minus_blood(minus)
print(Enemy.name + ":" + str(Enemy.blood))
def minus_blood(self,num):
self.blood -= num
def has_living(self):
if self.blood > 0:
return True
return False
class Hero(Sprite):
def bug_attack(self,Enemy):
Enemy.minus_blood(Enemy.blood)
def attack(self,Enemy):
super().attack(Enemy)
num = rn.randint(0,3)
if num == 1:
print(self.name + "使用了道具")
self.bug_attack(Enemy)
m = Sprite("monster")
n = Hero("hero")
while m.has_living() and n.has_living():
m.attack(n)
n.attack(m)
if m.has_living():
print("Monster Win")
elif n.has_living():
print("Hero Win")
else:
print("No Winer")
- 单例模式:
让该类只存在一个实例,多个对象也只调用一个实例。
class S:
instance = None
#__new__用来制作单例
def __new__(cls, *args, **kwargs):
if S.instance is None:
S.instance = super().__new__(cls)
return S.instance
s1 = S()
print(id(s1))
s2 = S()
print(id(s2))
继承
所有的类,都会默认继承Object类
class A:
def __init__(self):
self.name = 'A'
def print_test(self):
print("AAAAAAAAAA")
class B:
def __init__(self):
self.name = 'B'
class C(A):
def __init__(self):
#继承父类的属性
super().__init__()
self.age = 20
def print_test(self):
#继承父类的方法
super().print_test()
print("BBBBBBBB")
#python支持多继承,继承内容与继承顺序相关
class D(B,A):
pass
c = C()
print(c.name)
print(c.age)
c.print_test()
d = D()
print(d.name)
#类中查找属性或方法的搜索顺序,输出了多继承时类的搜索顺序
print(C.__mro__)
#继承需谨慎,组合优于继承
class F:
def __init__(self):
self.a = A()
def print_test(self):
self.a.print_test()
print("FFFFFFFFFF")
f = F()
f.print_test()
子类沿袭父类的属性和方法,也可以在此之上扩充
- 鸭子类型
鸭子类型:没有共同继承的两个类,但功能类似或相同,被称为鸭子类型
“叫起来像鸭子,走起来像鸭子,就是鸭子”
- 子类的对象也是父类的实例
print(isinstance(c,B))#c是否为B的实例
print(issubclass(B,A))#B是否为A的子类