封装

封装:就是将数据和功能'封装'起来
隐藏:在类的定义阶段名字前面使用两个下划线表示隐藏。就是将数据和功能隐藏起来不让用户直接调用,而是开发一些接口间接调用,从而可以在接口内添加额外的操作
伪装:将类里面的方法伪装成数据,目的是调用方法可以像调用数据一样不用加括号 """
隐藏类名称空间中名字的语法结构是在类的定义阶段名字前面加上__,那么通过类或者对象点名字的方式都无法直接找到这个名字,如果想要拿到语法结构为:类或对象._类名__名字
"""
class Myclass:
school_name = '清华大学'
_ = '嘿嘿嘿'
_name = 'max'
"""
类在定义阶段,名字前面有两个下划线,那么名字会被隐藏起来,无法直接访问
"""
__age = 25
"""
在python中,没有真正的隐藏,仅仅是换了个名字
"""
def __choice_course(self):
print('选课系统')
print(Myclass.school_name) # 清华大学
obj = Myclass()
print(obj.school_name) # 清华大学
print(Myclass._) # 嘿嘿嘿
print(obj._) # 嘿嘿嘿
print(Myclass._name) # max
print(obj._name) # max
print(Myclass.__age) # 会报错,因为__被隐藏
print(Myclass._Myclass__age) # 25
print(obj._Myclass__age) # 25
Myclass.__gender = 'male'
print(Myclass.__gender) # male 手动添加的类的名字无法隐藏
obj = Myclass()
obj.__addr = 'shanghai'
print(obj.__addr) # shanghai 手动添加对象的名字无法隐藏 """
除了类,对象也可以设置隐藏属性,但是只能在类体中设置,对象在类体中设置独有方式的方法就只有__init__方法。类体代码中可以直接用隐藏的名字
"""
class Person:
def __init__(self, name, age, hobby):
self.__name = name #对象也可以拥有隐藏的属性
self.__age = age
self.__hobby = hobby def get_info(self):
'''类体代码中可以直接用隐藏的名字'''
print(f"""
姓名:{self.__name}
年龄:{self.__age}
爱好:{self.__hobby}
""") '''隐藏的属性开放修改的接口,可以自定义很多功能,在这里定义一个修改功能'''
def set_name(self, new_name):
if len(new_name) == 0:
raise ValueError('修改的姓名不能为空')
if new_name.isdigit():
raise ValueError('名字不能是数字')
self.__name = new_name
obj = Person('max', 25, 'fitness')
obj.get_info()
"""
如果用__dict__查看对象名称空间,发现字典中所有的键都变成了:_类名__名字,所以说我们也可以通过对象名.__类名_名字的方式来拿对象的名字,但是不建议
"""

伪装

"""
类中有的功能返回值是一个数字,而我们调用的时候仍需要像调用函数一样调用,此时可以通过@property来装饰功能,使被装饰的功能从调用方式上来说更像一个数据
"""
BMI指数:衡量一个人的体重与身高对健康影响的一个指标
BMI=体重(kg)÷身高^2(m) class Person(object):
def __init__(self, name, height, weight):
self.name = name
self.height = height
self.weight = weight def BMI(self):
return self.weight / (self.height ** 2) p1 = Person('max', 1.82, 70)
print(p1.BMI()) # 21.132713440405748 有了@property之后功能BMI更像是一个数据,但是用该方法伪装不能加参数
class Person(object):
def __init__(self, name, height, weight):
self.name = name
self.height = height
self.weight = weight @property
def BMI(self):
return self.weight / (self.height ** 2) p1 = Person('max', 1.82, 70)
print(p1.BMI) # 21.132713440405748 """
当用property修饰之后的函数无法用对象名点名字的方式修改,此时用@函数名.setter修饰一个修改的函数,用户可以直接用对象名点的方式来修改
"""
class Foo:
def __init__(self, val):
self.__NAME = val @property
def name(self):
return self.__NAME @name.setter
def name(self, value):
if not isinstance(value, str):
raise TypeError('%s必须是字符串' % value)
self.__NAME = value @name.deleter
def name(self):
raise PermissionError('Can not delete') f1 = Foo('jason')
print(f1.name) # jason
f1.name = 'max' # 触发name.setter装饰器对应的函数
print(f1.name) # max
del f1.name # PermissionError: 不能被删除
# 触发name.deleter对应的函数name(f),抛出异常PermissionError """
用property装饰后的功能类似一个数据,查的时候只需要对象名点功能名即可查到。同样改和删也是以对象点函数名的方式来执行,改是用对象名点函数名等于新的值来调用修改功能,和之前的调用方式不同
"""

多态

1.多态:多态是指一种食物可以有多种形态但是针对相同的功能应该设定相同的方法,这样无论我们拿到的是哪个具体事务,都可以通过相同的方法调用功能(多态类型下父类的功能不再是为了省代码,而是提示每一个子类如果想要达成相同的目的必须要有相同的方法)
class Animal:
def spark(self):
pass def Cat(Animal):
def spark(self)
print('喵喵喵') def Dogs(Animal):
def spark(self)
print('汪汪汪') def Pig(Animal):
def spark(self)
print('哼哼哼')
"""
面向对象中多态意思是,一种事物可以有多种形态但是针对相同的功能应该定义相同的方法,这样无论我们拿到的是哪个具体的事物,都可以通过相同的方法调用功能
"""
s1 = 'hello world'
l1 = [11, 22, 33, 44]
d = {'name': 'jason', 'pwd': 123}
print(s1.__len__())
print(l1.__len__())
print(d.__len__()) 2.鸭子类型:只要你看上去像鸭子,走路像鸭子,说话像鸭子,那么你就是鸭子。以linux系统为例,文件能够读取数据也可以保存数据,内存能够读取数据也能保存数据吧,硬盘能够读取数据也能保存数据,所以在linux中有句话叫一切皆文件
eg:
class File:
def read(self): pass
def write(self): pass class Memory:
def read(self): pass
def write(self): pass class Disk:
def read(self): pass
def write(self): pass

反射

反射:利用字符串操作对象和数据的方法,可以动态地向对象中添加属性和方法
1.hasattr():
判断对象是否含有某个字符串对应的属性名或方法名
用法:hasaattr(obj,str),判断输入的str字符串在对象obj中是否存在(属性或方法),存在返回True,否则返回False
2.getattr():
根据字符串获取对象对应的属性名(数据)或方法(函数体代码)
用法:getattr(obj,str),将按照输入的str字符串在对象obj中查找。如找到同名属性,则返回该属性;如找到同名方法,则返回方法的引用,想要调用此方法得使用 getattr(obj,str)()进行调用.如果未能找到同名的属性或者方法,则抛出异常:AttributeError。
3.setattr():
根据字符串给对象设置或者修改数据
用法:setattr(obj,name,value),name为属性名或者方法名,value为属性值或者方法的引用
(1) 动态添加属性。如上
(2)动态添加方法。首先定义一个方法。再使用setattr(对象名,想要定义的方法名,所定义方法的方法名)
4.delattr():
根据字符串删除对象里面的名字
用法:delattr(obj,str),将你输入的字符串str在对象obj中查找,如找到同名属性或者方法就进行删除 """
判断某个名字对象是否存在
"""
class School:
school_name = '小姐姐学院'
def choice_course(self):
print('选课系统')
obj = School try:
obj.school_name
except Exception:
print('没有这个名字')
else: # try的子代码为True时走else子代码
print('名字存在哦')
# 执行结果:名字存在哦 """
请结合用户输入,查看用户输入的名字是否存在
"""
class School:
school_name = '小姐姐学院'
def choice_course(self):
print('选课系统')
obj = School target_name = input('请输入您想查看的名字>>>:').strip() try:
obj.target_name
except Exception:
print('没有这个名字')
else:
print('名字存在哦')
# 执行结果:没有这个名字
"""
因为获取用户输入得到的是字符串,而对象点的是变量名。反射的作用就是利用字符串操作对象的数据和方法
"""
print(hasattr(obj, 'school_name')) # True
print(getattr(obj, 'school_name')) # 小姐姐学院
print(getattr(obj, 'choice_course')) # <function School.choice_course at 0x0000020D15538598> """
hasattr和getattr找对象的数据和方法首先从对象名称空间中找,其次从产生对象的类名称空间中找,找不到再去父类名称空间中找
"""
class A:
name = 'jason' class B(A):
pass b = B()
print(getattr(b, 'name')) # jason """
判断用户输入的名字是否存在,如果存在则执行
"""
class C1:
school_name = '小姐姐学院'
def choice_course(self):
print('选课系统') obj = C1()
while True:
target_name = input('请输入您想要操作的名字>>>:').strip()
if hasattr(obj, target_name):
print('恭喜你,系统中有名字')
data_or_func = getattr(obj, target_name)
if callable(data_or_func):
print('您本次执行的是系统中的方法')
data_or_func()
else:
print('您本次执行的是系统中某个数据')
print(data_or_func)
else:
print('系统当中未找到该名字')

面向对象的魔法方法

魔法方法:类中定义的双下方法都称为魔法方法
使用方法:不需要认为调用,在特定条件下自动触发运行
eg:__init__是创建对象之后自动触发给对象添加独有数据的方法 1.__init__:添加对象独有数据的方法,对象添加数据时自动触发
class A:
def __init__(self, name):
self.name = name
print('__init__')
#类名加括号,给对象添加独有数据的方法
obj = A('max') # obj = A('max') 2.__str__:对象在被执行打印操作的时候自动触发,用法是在类体代码中定义__str__(self),先生成一个对象,在print(对象名),就可以自动触发打印返回值
class A:
def __str__(self):
'''对象在被执行打印操作的时候自动触发,并且返回什么执行结果就是什么'''
return '哈哈哈' # __str__子代码中不能用print,只能用return返回 a = A()
print(a) # 哈哈哈 """
返回值只能是字符串,非字符串数据类型会报错
"""
class A:
def __str__(self):
return 123 a = A()
print(a) # 报错 """
maximum recursion depth:最大递归深度;此代码报错原因是print(a)会自动触发__str__并且返回f'{self}说:哈哈哈',此时print(a就相当于print(f'{self}说:哈哈哈'),print里面反复递归对象a,直到达到最大递归深度报错,所以返回的字符串中不能有对象本身
"""
class A:
def __str__(self):
return f'{self}说:哈哈哈' a = A()
print(a) # 错误信息:RecursionError: maximum recursion depth exceeded while calling a Python object """
这个特性也可以用来分辨对象具体是谁, 返回的字符串中不能有对象本身,但可以点名字来看具体是哪个对象
"""
class A:
def __init__(self, name):
self.name = name def __str__(self):
return f'对象{self.name}' a = A('max')
print(a) # 对象max 3.__call__:对象加括号调用,该方法返回什么对象调用的返回值就是什么
class A:
def __init__(self, name):
self.name = name def __str__(self):
return f'对象{self.name}' def __call__(self, *args, **kwargs):
print('__call__')
return '__call__的返回值' a = A('max')
print(a()) # __call__ # __call__的返回值 """
对象类似于函数名,可以在括号内加上位置参数和关键字参数,打印args和kwargs可以看到他们分别收集了括号内的位置参数和关键字参数,对象名加括号可以调用__call__,print(res)还可以接受到__call__的返回值
"""
class A:
def __init__(self, name):
self.name = name def __str__(self):
return f'对象{self.name}' def __call__(self, *args, **kwargs):
print(args, kwargs)
return '__call__的返回值' a = A('max')
res = a(123, '123', name='max') # (123, '123') {'name': 'max'}
print(res) #__call__的返回值 4.__getattr__:对象点的名字不存在时自动触发
class A:
def __init__(self, name):
self.name = name def __getattr__(self, item):
return '很抱歉你找的名字不存在' a = A('max')
print(a.name) # max
print(a.age) # 很抱歉你找的名字不存在 5.__getattribute__:对象在查找名字时会自动触发,不管名字是否存在,并且只要有__getattribute__在,__getattr__会自动失效,例题中a.age不存在但是但是依然返回了'嘿嘿嘿',是因为__getattribute__作用将__getattr__覆盖
class A:
def __init__(self, name):
self.name = name def __getattr__(self, item):
return '很抱歉你找的名字不存在' def __getattribute__(self, item):
return '嘿嘿嘿' a = A('max')
print(a.name) # 嘿嘿嘿
print(a.age) # 嘿嘿嘿
"""
打印__getattribute__括号内的item后发现是一个对象名点的名字
"""
class A:
def __init__(self, name):
self.name = name def __getattr__(self, item):
return '很抱歉你找的名字不存在' def __getattribute__(self, item):
print(item)
return '嘿嘿嘿' a = A('max')
print(a.age) # age 嘿嘿嘿 5.__setattr__:当对象执行对象名.名字=值的时候(对象定义独有的数据或修改数据)就会自动触发
class A:
def __init__(self, name):
'''第一步:self此时就是a,满足对象名.名字=值,所以会执行一次__setattr__'''
self.name = name def __setattr__(self, key, value):
print('__setattr__') a = A('max')
a.name = 'jack' # __setattr__ __setattr__
'''第二步,再执行一次__setattr__''' """
__setattr__(self, key, value)中的key和value分别指name和值max
"""
class A:
def __init__(self, name):
self.name = name def __setattr__(self, key, value):
print('__setattr__')
print(key, value) class Student:
def __init__(self, name):
self.name = name a = A('max') # __setattr__ # name max 用__setattr__修改属性名:
obj1 = Student('max')
print(obj1.__dict__) # {'name': 'max'}
obj1.__setattr__('name', 'jason')
print(obj1.__dict__) # {'name': 'jason'} 6.__enter__:当对象跟在with后面,被当做上下文管理操作开始会自动触发__enter__。
__exit__:当对象参与with上下文管理语法运行完毕后自动触发(with子代码运行完毕)
class A:
def __init__(self, name):
self.name = name def __enter__(self):
print('enter')
return 123 def __exit__(self, exc_type, exc_val, exc_tb):
print('exit')
return 234 a = A('max')
with a as f:
print(f) # enter 123 exit """
a = A('max')
with a as f:
pass # enter exit
"""
由此得出,f拿到的是__enter__的返回值

魔法方法笔试题

1.补全下列代码使得运行不报错即可:
class Context:
pass
with Context() as f:
f.do_something()
"""
分析:有with 对象,说明with参与上下文管理,必须要有__enter__方法,结束时必须要有__exit__(这两者一般会联合使用)。此外do_something()还没有定义,还需要定义一个功能do_something(),调用时才不会报错
"""
class Context:
def do_something(self):
pass def __enter__(self):
return self
'''此行代码执行完毕需要一个f来点do_dometging(),我们一般用的最多的就是对象点的方式,所以此处需要返回对象本身也就是self。正好上节说道f拿到的是__enter__的返回值,所以旭阳将对象本身返回给f,再用对象点名字。所以return后面要跟self'''
def __exit__(self, exc_type, exc_val, exc_tb):
pass with Context() as f:
f.do_something() 2.请定义一个字典,该字典可以通过点的方式来取值
"""
我们之前学过点的方式取值,但是之前是通过对象点名字来取名称空间中的名字,而本题要求字典点的方式来取字典中的值,两者有本质区别
"""
'''1.定义一个类,该类可以派生字典里所有的方法'''
class Mydict(dict): '''2.由于添加键值对要通过点的方式来进行,那么可以联想到魔法方法中的__setattr__方法,该方法在对象名点名字=值时调用,且此时的key就指name,value指'max' '''
def __setattr__(self, key, value):
'''3.此时self就是obj,也就是构建的临时字典,通过按K取值的方式定义好取值方式'''
self[key] = value
'''4.定义好了添加键值对,此时再考虑取值。__getattr__特点是遇到名称空间中找不到的名字会自动触发,由于对象、类名称空间中都为空,所以查找名字肯定会自动触发__getattr__,且item是对象后面点的名字'''
def __getattr__(self, item):
'''5.返回一个通过item取到的值'''
return obj.get(item) obj = Mydict()
obj.name = 'max'
print(obj.name)

元类简介

元类概念推导:
步骤1:如何查看数据的数据类型
s1 = 'hello world' # str()
l1 = [11, 22, 33, 44] # list()
d1 = {'name': 'jason', 'pwd': 123} # dict()
t1 = (11, 22, 33, 44) # tuple()
print(type(s1)) # <class 'str'>
print(type(l1)) # <class 'list'>
print(type(d1)) # <class 'dict'>
print(type(t1)) # <class 'tuple'> 步骤2:type不仅可以查看数据类型,也可以查看产生对象的类名
class Group:
pass obj = Group()
print(type(obj)) # <class '__main__.Group'> 步骤3:type(对象名)结果是类名,那么type(类名)的结果是什么呢?
class Group:
pass obj = Group()
print(type(obj)) # <class '__main__.Group'>
print(type(Group)) # <class 'type'>
type的父类依然是type
print(type(type)) # <class 'type'>
"""
结论:我们定义的类归根结底都是type产生的,所以我们把产生类的类(type)叫做元类
"""

创建类的两种方式

方式1:通过关键字class创建
class Teacher:
name = 'jason'
age = 18 a = Teacher()
print(a.name, a.age) # jason 18 方式2:通过关键字type创建,语法结构:type(类名, 类的父类, 类的名称空间)
Teacher = type('Teacher', (), {'name': 'jason', 'age': 18})
a = Teacher()
print(a.name, a.age) # jason 18 """
也可以继承父类中的名字(如果只有一个父类后面需加逗号,同元组)
"""
class Person:
def work(self):
print('人不能不上班') Teacher = type('Teacher', (Person,), {'name': 'jason', 'age': 18})
a = Teacher()
print(a.work()) # 人不能不上班 None

元类参与类的产生行为

"""
在某一步设定一些条件,来干涉类产生的行为,对象是由类加括号产生的,类是由元类加括号产生的。
对象是由类名加括号产生的 __init__
类是由元类加括号产生的 __init__
"""
class MyMetaClass(type):
def __init__(cls, what, bases=None, dict=None):
print('what', what) # what Student
print('bases', bases) # bases ()
print('dict', dict) # dict {'__module__': '__main__', '__qualname__': 'Student', 'name': 'max'}
super().__init__(what, bases, dict) '''通过metaclass=MyMetaClass来继承元类'''
class Student(metaclass=MyMetaClass):
name = 'max'
"""
通过依次打印what, bases, dict得知,what是继承了MyMetaClass的类,dict是类Student的名称空间
""" class MyMetaClass(type):
def __init__(cls, what, bases=None, dict=None):
# print('what', what) # what Student
# print('bases', bases) # bases ()
# print('dict', dict) # dict {'__module__': '__main__', '__qualname__': 'Student', 'name': 'max'}
if not what.istitle():
raise TypeError('首字母必须大写') super().__init__(what, bases, dict) class student(metaclass=MyMetaClass):
name = 'max' # TypeError: 首字母必须大写 class Student(metaclass=MyMetaClass):
name = 'max' # 可以正常创建

元类参与对象的产生行为

"""
对象加括号会执行产生该对象类里面的__call__
推导得出:类加括号会执行产生该类的类里面的__call__
"""
"""
给对象添加一些独有数据,首先是传到了元类里面的__call__,位置参数传给了args,关键字参数传给了kwargs,其次再交给__init__
"""
class MyMetaClass(type):
def __call__(self, *args, **kwargs):
print('__call__')
print(args, kwargs)
super().__call__(*args, **kwargs) class Student(metaclass=MyMetaClass):
def __init__(self, name, age, gender):
print('__init__')
self.name = name
self.age = age
self.gender = gender obj = Student('max', 25, 'male')
'''
执行结果:
__call__
('max', 25, 'male') {}
__init__
'''
要求:定义一个类,声称对象只能上传关键字参数
class MyMetaClass(type):
def __call__(self, *args, **kwargs):
if args:
raise TypeError('必须要传关键词参数哦')
'''super语句前面一定要加上return,不加会报错'''
return super().__call__(*args, **kwargs) class Student(metaclass=MyMetaClass):
def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender = gender # obj = Student('max', 25, 'male') # TypeError: 必须要传关键词参数哦
obj = Student(name='max', age=25, gender='male')
print(obj.__dict__) # {'name': 'max', 'age': 25, 'gender': 'male'}
"""
分析:为什么要用类Student继承元类MyMetaClass呢?
因为对象产生的过程中首先把参数传入MyMetaClass的__call__,只有用Student继承元类MyMetaClass才能介入对象的生成过程。 如果args布尔值为True说明上传了关键字参数,这种情况下主动报错,报错情况下不会执行,只有args布尔值为Flase时才会执行super语句
"""

设计模式简介

1.设计模式:前人通过大量的验证创建出来解决一些问题的固定高效方法
2.IT行业目前有23种设计模式。分类:创建型、结构型、行为型
3.单例模式
类加括号无论执行多少次永远只会产生一个对象
目的:
当类中有很多非常强大的方法 我们在程序中很多地方都需要使用
如果不做单例 会产生很多无用的对象浪费存储空间
我们想着使用单例模式 整个程序就用一个对象

单例模式实现

方式1:类中存储单例
class C1:
__isinstance = None # 1.定义一个全局变量
def __init__(self, name, age):
self.name = name
self.age = age '''通过这种方法产生一个固定的对象,并且只能调用此种方式产生'''
@classmethod
def singleton(cls): # 2.通过classmethond修饰的函数可以直接将类传进去
if not cls.__isinstance: # 3.判断,通过类.名字的方式拿到类中的数据
cls.__isinstance = cls('max', 123) # 4.如果cls.instance为None,则把它修改为一个对象,cls('max', 123)是一个对象
return cls.__isinstance # 5.返回刚刚生成的对象,拿到的返回值都是对象C1('max', 123) obj1 = C1.singleton()
obj2 = C1.singleton()
print(id(obj1), id(obj2))
# 1952330470792 1952330470792
"""
此种方法也可以产生正常的对象,不调用singleton方法就可以正常产生
""" 方法2:通过模块来实现单例模式
md.py文件中代码:
class C1:
def __init__(self, name):
self.name = name obj = C1('jason') 另一个py文件:
import md
print(id(md.obj)) # 2278381247176 print(id(md.obj)) # 2278381247176 方式3:元类控制单例类的产生
class MyType(type):
def __init__(cls, what, bases=None, dict=None): # 1.定义一个类
cls.__instance = cls.__new__(cls) # 2.用双下__new__产生一个新对象
cls.__init__(cls.__instance, 'jason', 18) # 3.添加对象独有的数据
super().__init__(what, bases, dict) # 4.继承元类其它的方法 def __call__(cls, *args, **kwargs): # 6.类的对象加括号调用类的__call__,子类加括号调用父类__call__
if args or kwargs: # 7.如果子类中传了值,就正常给对象添加独有数据,并且返回该对象
obj = cls.__new__(cls)
cls.__init__(obj, *args, **kwargs)
return obj
return cls.__instance # 8.如果子类对象没有添加数据,则返回之前创建的对象 class Mysql(metaclass=MyType): # 5.定义类Mysql,父类是MyType
def __init__(self, name, age):
self.name = name
self.age = age obj1 = Mysql() # 9.所以Mysql产生的对象如果不加参数
obj2 = Mysql()
print(id(obj1), id(obj2)) # 2675820190128 2675820190128

pickle序列化

1.优势:能够序列化python中所有的类型
2.缺陷:只能够在python中使用,无法跨语言传输
3.功能:产生一个对象并且保存在文件中,取出时还是一个对象 class C1:
def __init__(self, name, age):
self.name = name
self.age = age def func1(self):
print('from func1') def func2(self):
print('from func2') obj = C1('max', 25) import json
with open(r'a.txt', 'w', encoding='utf8') as f:
json.dump(obj, f) # TypeError: Object of type C1 is not JSON serializable,说明json模块无法将对象存入文件 import pickle
with open(r'a.txt', 'wb') as f:
pickle.dump(obj, f) with open(r'a.txt', 'rb')as f:
data = pickle.load(f)
print(data) # <__main__.C1 object at 0x000001F214678C50>
data.func1() # from func1
data.func2() # from func2
print(data.name) # max

选课系统思路

1.管理员功能
注册功能
"""
1.获取用户输入的用户名和密码,传到第二层
2.根据类名和用户名获取到用户对象,如果有对象说明用户已注册,返回False
3.如果对象不存在则创建新的对象并保存,返回True
"""
登录功能
"""
1.获取用户输入的用户名和密码,传到第二层
2.根据类名和用户名获取到用户对象,如果有没有对象说明用户未注册,返回False
3.如果能找得到对象,并且密码可以和对象中的密码(对象独有的数据)对上,那么返回True,并且修改记录用户登陆的字典
"""
创建学校
"""
1.事先在models中创建好School的类,包含名字和地址属性
2.在第一层获取学校的名字和地址,传入第二层
3.先利用学校名获取学校对象,如果学校已经存在则返回已注册,不存在则利用管理员对象点方法的形式生成学校对象
"""
创建课程
"""
1.先循环打印所有的学校,让用户选择添加课程的学校
2.获取用户输入得到课程信息,将课程信息,目标学校,管理员姓名传入第二层
3.查看该课程是否在学校的课程列表中,如果存在则返回信息无法添加,如果不在则利用管理员对象创建课程对象
4.在学校对象的课程列表中添加该课程
"""
创建老师
"""
1.获取用户输入,得到老师姓名和密码
2.传给第二层,生成老师对象,如果对象存在说明已经注册过,无法创建;如果对象不存在可以正常创建
"""
2.讲师功能
登录功能
"""
1.获取用户输入的用户名和密码,传到第二层
2.根据类名和用户名获取到用户对象,如果有没有对象说明用户未注册,返回False
3.如果能找得到对象,并且密码可以和对象中的密码(对象独有的数据)对上,那么返回True,并且修改记录用户登陆的字典
"""
查看课程
"""
1.循环遍历所有学校,供用户选择
2.用学校名拿到学校对象,返回课程列表
"""
选择课程
"""
1.循环打印所有的课程,供老师选择,建立一个临时列表,选择的课程添加在临时列表里
2.用集合去重的特性将老师原来的课程列表和临时课程列表合二为一,修改老师的课程列表
3.课程列表中逐一添加老师
"""
查看学生分数
"""
1.先在第二层获取该老师教授的课程列表,返回第一层
2.循环打印课程列表,让用户选择一门课程
3.在第二层获取该门课程的学生列表,并且利用字典生成式返回该学生的成绩字典
"""
修改学生分数
"""
1.先获取老师教授的课程列表,循环打印让老师选择目标课程
2.在第二层获取该课程的学生列表,并返回第一层让用户选择目标学生
3.获取用户输入的目标课程的最新分数,将目标课程,最新分数,学生姓名,老师姓名传入第二层
4.获取学生对象,再拿到学生的成绩字典,修改,保存
"""
3.学生功能
注册功能
"""
1.获取用户输入的用户名和密码,传到第二层
2.根据类名和用户名获取到用户对象,如果有对象说明用户已注册,返回False
3.如果对象不存在则创建新的对象并保存,返回True
"""
登录功能
"""
1.获取用户输入的用户名和密码,传到第二层
2.根据类名和用户名获取到用户对象,如果有没有对象说明用户未注册,返回False
3.如果能找得到对象,并且密码可以和对象中的密码(对象独有的数据)对上,那么返回True,并且修改记录用户登陆的字典
"""
选择学校
"""
1.循环打印所有学校名字
2.让用户选择学校;在第二层获取学生对象,用点的方式查看用户是否已选学校
3.如果有则无法修改学校,没有则在对象中添加学校
"""
选择课程
"""
1.先获取学生对象,然后判断学生是否已选学校,如果已选学校,返回学校课程列表
2.在第一层循环遍打印课程列表,让用户选择要添加的课程,形成一个临时字典
3.用集合将临时字典和旧的学生课程列表合二为一,修改学生的课程列表
4.遍历新的学生课程列表,更新成绩字典
"""
查看成绩
"""
1.全局名称空间中的学生姓名传到第二层,生成学生对象
2.直接返回成绩字典
"""

python学习第六周总结的更多相关文章

  1. python学习第六讲,python中的数据类型,列表,元祖,字典,之列表使用与介绍

    目录 python学习第六讲,python中的数据类型,列表,元祖,字典,之列表使用与介绍. 二丶列表,其它语言称为数组 1.列表的定义,以及语法 2.列表的使用,以及常用方法. 3.列表的常用操作 ...

  2. Python学习第六课

    Python学习第六课 课前回顾 列表 创建 通过 [] :写在[]里,元素之间用逗号隔开 对应操作: 查 增 append insert 改(重新赋值) 删除(remove del pop(删除后会 ...

  3. java学习第六周

    这是暑假学习的第六周,在这周我练习了老师给的例题,还是有一些地方看不懂,这周我对那些不懂的地方用看视频来进行解答,以及进行第二次复习. 下周我会对Java进行更加详细的复习,做好笔记,在LeetCod ...

  4. Python学习笔记六

    Python课堂笔记六 常用模块已经可以在单位实际项目中使用,可以实现运维自动化.无需手工备份文件,数据库,拷贝,压缩. 常用模块 time模块 time.time time.localtime ti ...

  5. python学习笔记第二周

    目录 一.基础概念 1.模块 1)os模块 2)sys模块 2.pyc文件 3.数据类型 1)数字 2)布尔值 3)字符串 4.数据运算 5.运算符 6.赋值运算 7.逻辑运算 8.成员运算 9.身份 ...

  6. python学习笔记六 面向对象相关下(基础篇)

    面向对象基本知识: 面向对象是一种编程方式,此编程方式的实现是基于对 类 和 对象 的使用 类 是一个模板,模板中包装了多个“函数”供使用(可以将多函数中公用的变量封装到对象中) 对象,根据模板创建的 ...

  7. python学习笔记六 初识面向对象上(基础篇)

    python面向对象   面向对象编程(Object-Oriented Programming )介绍   对于编程语言的初学者来讲,OOP不是一个很容易理解的编程方式,虽然大家都知道OOP的三大特性 ...

  8. Python学习(六) —— 函数

    一.函数的定义和调用 为什么要用函数:例如,计算一个数据的长度,可以用一段代码实现,每次需要计算数据的长度都可以用这段代码,如果是一段代码,可读性差,重复代码多: 但是如果把这段代码封装成一个函数,用 ...

  9. Python学习(六)模块

    Python 模块 模块定义 随着程序越来越庞大,需要分隔成几个文件:也需要能在不同文件中复用函数.类和变量,而不是拷贝代码.为了满足这些需要,Python提供了模块. 简单来说,模块就是一个保存了P ...

  10. Python学习(六)模块 —— 标准模块

    Python 标准模块 Python 带有一个标准模块库,并发布有独立的文档(库参考手册).对于程序员而言,标准库与语言本身同样重要,它好比一个百宝箱,能为各种常见的任务提供完美的解决方案. 这边简单 ...

随机推荐

  1. 图扑软件 3D 组态编辑器,低代码零代码构建数字孪生工厂

    行业背景 随着中国制造 2025 计划的提出,新一轮的工业改革拉开序幕.大数据积累的指数级增长为智能商业爆发奠定了良好的基础,传统制造业高污染.高能耗.低效率的生产模式已不符合现代工业要求. 图扑拖拽 ...

  2. Docker | 常用命令——排错很有帮助

    众所周知,docker 排查问题相较而言是困难的.因此,熟知一些常用命令对我们快速的排查定位问题是非常有帮助的.下面让我们一起来学习一下吧 1.显示docker的系统信息 docker info [r ...

  3. Debian Linux 的安装

    Debian Linux 的安装 作者:Grey 原文地址: 博客园:Debian Linux 的安装 CSDN:Debian Linux 的安装 说明 本安装说明是基于 Windows 10 下 V ...

  4. EasyExcel对大数据量表格操作导入导出

    前言 最近有个项目里面中有大量的Excel文档导入导出需求,数据量最多的文档有上百万条数据,之前的导入导出都是用apache的POI,于是这次也决定使用POI,结果导入一个四十多万的文档就GG了,内存 ...

  5. 【云原生 · Kubernetes】部署 kube-proxy 组件

    个人名片: 因为云计算成为了监控工程师‍ 个人博客:念舒_C.ying CSDN主页️:念舒_C.ying kube-proxy 运行在所有 worker 节点上,它监听 apiserver 中 se ...

  6. 【云原生 · Kubernetes】Kubernetes容器云平台部署与运维

    [题目1]Deployment管理 在master节点/root目录下编写yaml文件nginx-deployment.yaml,具体要求如下: (1)Deployment名称:nginx-deplo ...

  7. Python中 or、and 的优先级

    上式可以看出  先看 and 输出才为 ture 因此  优先级 and>or

  8. 【实时数仓】Day05-ClickHouse:入门、安装、数据类型、表引擎、SQL操作、副本、分片集群

    一.ClickHouse入门 1.介绍 是一个开源的列式存储数据库(DBMS) 使用C++编写 用于在线分析查询(OLAP) 能够使用SQL查询实时生成分析数据报告 2.特点 (1)列式存储 比较: ...

  9. 跳出foreach循环

    直接return false没用,需要用throw来跳出foreach 1 try { 2 this.categoryList.forEach((item, index) => { 3 if ( ...

  10. 像go 一样 打造.NET 单文件应用程序的编译器项目bflat 发布 7.0版本

    现代.NET和C#在低级/系统程序以及与C/C++/Rust等互操作方面的能力完全令各位刮目相看了,有人用C#开发的64位操作系统: GitHub - nifanfa/MOOS: C# x64 ope ...