1,两个装饰器函数
@classmethod
被装饰的方法会成为一个静态方法 1,什么时候用 在修改类当中的某个变量,又不想实例化他,在实例化之前就去操作的情况下。 2,怎么定义? 1,装饰器怎么加? 2,参数怎么改? 3,怎么用? 1,用谁来调用?
class Goods:
__discount = 0.8
def __init__(self):
self.__price = 5
self.price = self.__price * self.__discount
def change_discount(self, new_discount):
Goods.__discount = new_discount
Goods.change_discount(0.6)
apple = Goods()
print(apple.price)
# x修改折扣,将8折改成折
apple.change_discount(0.6) # 类方法可以通过对象名调用
apple2 = Goods()
print(apple2.price)
# 上述的方法在逻辑上有一些问题
使用classmethod
定义一个方法,默认传self,但是这个self没被使用 @classmethod 把一个对象绑定的方法修改成一个类方法 优势: 1,在方法中仍然可以引用类中的静态变量 2,可以不用实例化对象,就直接用类名在外部调用方法 什么时候用@classmethod; 1,用不到对象,并且要用到类名的时候 2,定义了一个方法,默认传self,但是这个self没被使用 3,并且你在这个方法里用到了当前的类名,或者你准备使用这个类的内存空间中的名字的时候
class Goods:
__discount = 0.8
def __init__(self):
self.__price = 5
self.price = self.__price * self.__discount
@classmethod
def change_discount(cls, new_discount): # 此时cls是指向Goods
cls.__discount = new_discount # 这里不管类名是什么cls都是代表类名
Goods.change_discount(0.6) # 可以通过类名调用类方法
apple = Goods()
print(apple.price)
# 实例化***
import time
class Date:
def __init__(self, year, month, day):
self.year = year
self.month = month
self.day = day
@classmethod
def today(cls):
struct_t = time.localtime()
print(struct_t.tm_year)
print(struct_t.tm_mon)
print(struct_t.tm_mday)
return date
date = Date() # 此时调用Date还需要传参
date.today()
# import time
class Date:
def __init__(self, year, month, day):
self.year = year
self.month = month
self.day = day
@classmethod
def today(cls):
struct_t = time.localtime()
date = cls(struct_t.tm_year, struct_t.tm_mon, struct_t.tm_mday)
return date
date = Date.today()
print(date.year)
print(date.month)
print(date.day)
@staticmethod
1,什么时候用? 帮助我们把普通的函数挪到类中啦直接使用,制造静态方法用的 2,怎么定义? 3,怎么用? 用谁来调
@staticmethod* 被装饰的方法会成为一个静态方法
class User:
pass
@staticmethod
def login(a, b): # 本身是一个普通函数,被挪到类的内部执行那么直接给这个函数添加@staticmethod装饰器就可以了,但是调用时还是要通过类名调用。
print('登录的逻辑', a, b)
# 在函数的内部既不会用到self变量,也不会用到cls类
obj = User()
obj.login(1, 2) # 既可以用类名定义
User.login(3, 4) # 也可以用对象调用
class A:
countr = '中国'
def fuc(self):
print(self.__dict__)
@classmethod
def clas_func(cls):
print(cls)
@staticmethod
def stat_func():
print('普通函数')
@property
def name(self):
print('property方法')
'''
能定义到类中的内容:
静态变量:country = '中国'
# 所有的对象共享的变量
绑定方法:含有self的方法 由对象调用
# 是个自带self参数的函数
class A:
countr = '中国'
def fuc(self);
print(self.__dict__)
类方法:加上@classmethod的装饰器用cls作为参数的方法
# 自带cls的参数 由对象/类调用
@classmethod
def clas_func(cls);
print(cls)
静态方法:@staticmethod 将类中的方法,变成一个普通的函数,不需要传参
# 啥都不带的普通函数 有对象/类调用
@staticmethod
def stat_func():
print('普通函数')
property属性:是个伪装成属性的方法 由对象调用 但是不加括号
'''
2,一些内置的魔术方法
一些内置的魔术方法: __new__:构造方法,实例化对象的时候使用,用来开辟空间的 单例模式(默写) __call__:只要类中有__call__方法 就可以用对象() 调用 __len__:len(对象) 需要实现这个类中的__len__方法 只要类中有__len__方法,就可以直接使用len()函数 __str__:帮助我们在打印\展示对象的时候更直观的显示对象内容 %s字符串拼接 str()类型强制转换 print() __repr__:repr是str的备胎,同时还和%r和repr的时候就只会显示这个方法的返回值 item系列 __gettitem__ __hash__ enter/exit del
1,__call__
# 1,__call__
# callable(对象)
# 对象能不能运行就是callable判断的事儿(就是看这个类里面有没有__call__方法)
class A:
def __call__(self, *args, **kwargs):
print('-------')
obj = A()
print(callable(obj))
obj() # 对象加括号就是调用这个类下面的__call__方法
# Flask框架的源码使用__call__
2,__len__
class Cls:
def __init__(self, name):
self.name = name
self.student = []
def __len__(self):
return len(self.student)
py22 = Cls('py22')
py22.student.append('alex')
py22.student.append('taibai')
py22.student.append('wusir')
print(len(py22)) # 3
# 例子,(理解__len__)
class Pow:
def __init__(self, n):
self.n = n
def __pow2__(self):
return self.n ** 2
def pow2(obj):
return obj.__pow2__()
obj = Pow(10)
print(pow2(obj))
3,__new__:单例模式***
class A:
def __new__(cls, *args, **kwargs): # 构造方法
o = super().__new__(cls)
print('执行new', o)
return o
def __init__(self):
print('执行init', self)
A()
实例化的时候 先创建一块对象空间,有一个指针能指向类---> __new__ 再调用init __new__没有返回值就不会调用__init__
设计模式 -- 单例模式 一个类从头到尾 只会创建一次self空间
class Baby:
__instance = None
def __new__(cls, *args, **kwargs):
if cls.__instance is None:
cls.__instance = super().__new__(cls)
return cls.__instance
def __init__(self, cloth, pants):
self.cloth = cloth
self.pants = pants
b1 = Baby('红毛衣', '绿皮裤')
b2 = Baby('白衬衫', '黑豹纹')
b3 = Baby('西装', '牛仔裤')
print(b1.cloth)
print(b2.cloth)
print(b3.cloth)
4,__str__
class Course:
def __init__(self, name, price, period):
self.name = name
self.price = price
self.period = period
def __str__(self): # 作用就是查看的时候是一个直观地值,而不是内存地址
return ','.join([self.name, str(self.price), self.period])
python = Course('python', 21800, '6months')
linux = Course('linux', 19800, '5months')
mysql = Course('mysql', 12800, '4months')
go = Course('go', 15800, '4months')
lst = [python, linux, mysql, go]
for course in lst:
print(course)
for index, i in enumerate(lst, 1):
num = int(input('请输入您要选择的课程>>>'))
course = lst[num-1]
print(f'恭喜您选课成功,您选的课程是{course.name},价格{course.price}元')
print(index, i.name)
使用场景
1,在打印一个对象的时候 调用__str__方法
2,在%拼接一个对象的时候 调用__str__方法
3,在str一个对象的时候 调用__str__方法
class clas:
def __init__(self):
self.student = []
def append(self, name):
self.student.append(name)
def __str__(self): #如果不使用__str__(),打印出来的全是内存地址
return str(self.student)
# 场景一
py22 = clas()
print(py22)
py22.append('大壮') # ['大壮']
print(py22)
# 场景二
py21 = clas()
py21.append('大壮')
print('我们py21班 %s'%py21) # 我们py21班 ['大壮']
# 场景三
py21 = clas()
py21.append('大壮')
print(str(py21)) # ['大壮']
5,__repr__: 和__str__作用相同
1,当我们打印一个对象 用%s进行字符串拼接 或者str(对象)总是调用这个对象的__str__方法 如果找不到__str__,就调用__repr__方法。 2,__repr__不仅仅是__str__的替代品,还有自己的功能 用%r进行字符穿拼接 或者用repr(对象)的时候总是会调用这个对象的__repr__方法
class clas:
def __init__(self):
self.student = []
def append(self, name):
self.student.append(name)
def __repr__(self):
return str(self.student)
def __str__(self):
return 'aaaa'
py22 = clas()
print(py22)
py22.append('大壮')
print(py22) # ['大壮']
print('我们py22班 %s' % py22) # 我们py22班 aaaa
print('我们py22班 %r' % py22) # 我们py22班 ['大壮']
4,__eq__:判断相等
==这个符号刚好会调用alex对象对应的类的__eq__方法,ale会被当做self参数传入方法,alex222会被当做other参数传入方法 alex == alex222 的结果就是__eq__方法的返回值
# __gt__: 大于 # __lt__: 小于
class Person(object):
def __init__(self, name, age):
self.name = name
self.age = age
def __eq__(self, other):
print('开始执行我了')
print(self)
print(other)
print('执行完了')
return 'aaaaaaaaaaa'
alex = Person('alex', 84)
alex222 = Person('alex', 84)
print('-' * 20)
print(alex == alex222)
3,学生系统项目
功能描述
'''
学生选课:核心功能只有选课
角色:学生,管理员
功能:
1,登录:管理员和学生都可以登录,且登录之后可以自动区分身份
2,选课:学生可以自由的为自己选择课程
3,创建用户:选课系统是面向本校的学生,因此所有的用户都应该由管理员完成
4,查看选课情况:每个学生可以查看自己的选课情况,而管理员应该可以查看所有学生的信息
工作流程:
1,学生:
1,登录:用户输入用户名和密码
2,判断身份:在登录的时候应该可以直接判断出用户的身份是学生还是管理员
3,学生用户:对于学生来说,登录之后有三个功能
a) 查看所有课程
b) 选择课程
c) 查看所选的课程
d) 退出程序
2,管理员用户:管理员用户除了可以做一些查看功能之外,还有很多创建工作
1,创建课程
2,创建学生账号
3,查看所有课程
4,查看所有学生
5,查看所有学生的选课情况
6,退出程序
3,属性,方法
1,课程:
属性:课程名,价格,周期,老师
2,学生:
属性:姓名,所选课程
方法:查看可选的课程,选择课程,查看所选课程,退出程序
3,管理员:
属性:姓名
方法:创建课程,创建学生账号,查看所有学生,查看所有学生的选课情况,退出程序
'''
新建一个userinfo文件存储用户名、用户密码和身份
文件的路径需要自己修改
例
alex|000|Manager yutao|123456|Student
import pickle
USERINFO = r'D:\python 代码文件\python全栈学习\01-python基础\18-面向对象收尾\学生系统项目\代码\userinfo'
STUINFO = r'D:\python 代码文件\python全栈学习\01-python基础\18-面向对象收尾\学生系统项目\代码\stuinfo'
class Course: # 课程类
def __init__(self, name, price, period):
self.name = name
self.price = price
self.period = period
'''
创建学生
让用户输入用户名 密码
实例化一个对象
把用户名 密码写到userinfo
把学生对象信息写到stuinfo文件里,将用户名密码和用户信息分开
'''
class Student:
opt_lst = [('查看课程', 'show_courses'), ('选择课程', 'choose_course'),
('查看已选课程', 'show_selected'), ('退出', 'exit')]
def __init__(self, name):
self.name = name
self.courses = [] # 每一个学生一进行注册就有一个空的课程列表
def show_courses(self):
pass
def choose_course(self):
pass
def show_selected(self):
pass
def __exit__(self):
pass
class Manager(object):
opt_lst = [('创建课程', 'create_course'), ('创建学生', 'create_student'),
('查看课程', 'show_courses'), ('查看学生', 'show_students'),
('查看学生和已选课程', 'show_stu_course'), ('退出', 'exit')]
def __init__(self, name):
self.name = name
def create_course(self):
pass
def create_student(self):
user = input('请输入创建的用户名:')
pwd = '123456'
stu = Student(user)
with open(USERINFO, mode='a', encoding='utf-8') as f:
f.write(f'{user}|123456|Student\n')
with open(STUINFO, mode='ab') as f:
pickle.dump(stu, f) # pickle之后数据是二进制的数据
print(f'{stu.name}创建成功---操作员{self.name}')
def show_courses(self):
pass
def show_students(self):
pass
def show_stu_course(self):
pass
def __exit__(self):
pass
#
# @classmethod
# def init(cls,ret):
# obj = cls(ret[0])
# return obj
# 用户 输入用户名 密码判断用户是否合法和身份是啥?
def login():
'''
:return: 登录成功:返回用户名 身份
登录失败
'''
username = input('username:')
password = input('passwors:')
with open(USERINFO, 'r', encoding='utf-8') as f:
for line in f:
user, pwd, ident = line.strip().split('|')
if user == username and password == pwd:
return user, ident
else:
return False
ret = login()
if ret:
print(f'登录成功!{ret[0]},欢迎使用选课系统')
if ret[1] == 'Manager':
m = Manager(ret[0])
for index, opt in enumerate(Manager.opt_lst, 1):
print(index, opt[0])
num = int(input('您要选择的操作:').strip())
if hasattr(m, Manager.opt_lst[num - 1][1]):
getattr(m, Manager.opt_lst[num - 1][1])()
elif ret[1] == 'Student':
with open(STUINFO, 'rb') as f:
while True:
try:
obj = pickle.load(f)
if obj.name == ret[0]:
stu = obj
break
except EOFError:
print('没有这个学生')
s = Student(ret[0])
for index, opt in enumerate(Student.opt_lst, 1):
print(index, opt[0])
num = int(input('您要选择的操作:').strip())
if hasattr(s, Student.opt_lst[num - 1][1]):
getattr(s, Student.opt_lst[num - 1][1])()
else:
print('登录失败!')
优化版:
import pickle
import sys
USERINFO = r'D:\python 代码文件\python全栈学习\01-python基础\18-面向对象收尾\学生系统项目\代码\userinfo'
STUINFO = r'D:\python 代码文件\python全栈学习\01-python基础\18-面向对象收尾\学生系统项目\代码\stuinfo'
class Course: # 课程类
def __init__(self, name, price, period):
self.name = name
self.price = price
self.period = period
'''
创建学生
让用户输入用户名 密码
实例化一个对象
把用户名 密码写到userinfo
把学生对象信息写到stuinfo文件里,将用户名密码和用户信息分开
'''
class Student:
opt_lst = [('查看课程', 'show_courses'), ('选择课程', 'choose_course'),
('查看已选课程', 'show_selected'), ('退出', 'exit')]
def __init__(self, name):
self.name = name
self.courses = [] # 每一个学生一进行注册就有一个空的课程列表
def show_courses(self):
pass
def choose_course(self):
pass
def show_selected(self):
pass
def __exit__(self):
pass
@staticmethod
def init(ret):
with open(STUINFO, 'rb') as f:
while True:
try:
obj = pickle.load(f)
if obj.name == ret[0]:
return obj
except EOFError: print('没有这个学生')
class Manager(object):
opt_lst = [('创建课程', 'create_course'), ('创建学生', 'create_student'),
('查看课程', 'show_courses'), ('查看学生', 'show_students'),
('查看学生和已选课程', 'show_stu_course'), ('退出', 'exit')]
def __init__(self, name):
self.name = name
def create_course(self):
pass
def create_student(self):
user = input('请输入创建的用户名:')
pwd = '123456'
stu = Student(user)
with open(USERINFO, mode='a', encoding='utf-8') as f:
f.write(f'{user}|123456|Student\n')
with open(STUINFO, mode='ab') as f:
pickle.dump(stu, f) # pickle之后数据是二进制的数据
print(f'{stu.name}创建成功---操作员{self.name}')
def show_courses(self):
pass
def show_students(self):
pass
def show_stu_course(self):
pass
def __exit__(self):
pass
@classmethod
def init(cls,ret):
obj = cls(ret[0])
return obj
# 用户 输入用户名 密码判断用户是否合法和身份是啥?
def login():
'''
:return: 登录成功:返回用户名 身份
登录失败
'''
username = input('username:')
password = input('passwors:')
with open(USERINFO, 'r', encoding='utf-8') as f:
for line in f:
user, pwd, ident = line.strip().split('|')
if user == username and password == pwd:
return user, ident
else:
return False
# ----------------------------------------------------------------------------------------------------------------------
# 优化后的代码::
ret = login()
if ret:
print(f'登录成功!{ret[0]},欢迎使用选课系统')
cls = getattr(sys.modules[__name__], ret[0])
obj = cls.init(ret)
for index, opt in enumerate(cls.opt_lst, 1):
print(index, opt[0])
num = int(input('您要选择的操作:').strip())
if hasattr(obj, Student.opt_lst[num - 1][1]):
getattr(obj, Student.opt_lst[num - 1][1])()
# ----------------------------------------------------------------------------------------------------------------------
# ret = login()
# if ret:
# print(f'登录成功!{ret[0]},欢迎使用选课系统')
# if ret[1] == 'Manager':
# m = Manager(ret[0])
# for index, opt in enumerate(Manager.opt_lst, 1):
# print(index, opt[0])
# num = int(input('您要选择的操作:').strip())
# if hasattr(m, Manager.opt_lst[num - 1][1]):
# getattr(m, Manager.opt_lst[num - 1][1])()
# elif ret[1] == 'Student':
# with open(STUINFO, 'rb') as f:
# while True:
# try:
# obj = pickle.load(f)
# if obj.name == ret[0]:
# stu = obj
# break
# except EOFError:
# print('没有这个学生')
# s = Student(ret[0])
# for index, opt in enumerate(Student.opt_lst, 1):
# print(index, opt[0])
# num = int(input('您要选择的操作:').strip())
# if hasattr(s, Student.opt_lst[num - 1][1]):
# getattr(s, Student.opt_lst[num - 1][1])()
else:
print('登录失败!')
4,练习题目
1,阅读代码,写结果
class Foo(object):
def __init__(self, name):
self.name = name
v1 = [Foo for i in range(10)]
v2 = [Foo(5) for i in range(10)]
v3 = [Foo(i) for i in range(10)]
print(v1)
print(v2)
print(v3)
2,阅读代码,写结果
class Person(object):
def __init__(self, name, age):
self.name = name
self.age = age
def __eq__(self, other):
print('开始执行我了')
print(self)
print(other)
print('执行完了')
return 'aaaaaaaaaaa'
alex = Person('alex', 84)
alex222 = Person('alex', 84)
print('-' * 20)
print(alex == alex222)
print('*' * 20)
print(alex is alex222)
3,阅读代码,写结果
class Person(object):
def __init__(self, name, age):
self.name = name
self.age = age
def __eq__(self, other): # 两个对象作比较的时候自动调用这个方法
if self.age == other.age and self.name == other.name:
return 'True'
else:
return 'False'
def __gt__(self, other):
print('执行gt啦')
def __lt__(self, other):
print('执行lt啦')
alex = Person('alex', 83)
alex222 = Person('alex', 84)
print(alex == alex222)
更多内容可以查看自己学python的过程,简单笔记。-CSDN博客
更多内容可以查看自己学python的过程,简单笔记。-CSDN博客
更多内容可以查看自己学python的过程,简单笔记。-CSDN博客