嵌套
#coding:utf-8
class School(object):
def __init__(self,name,addr):
self.name =name
self.addr = addr
def classes(self):
print(f"到{self.name}该班级上课")
class Teacher(object):
def __init__(self,name,age,salary,school=None):
self.name=name
self.age = age
self.__salary = salary
self.school = school
s1=School("蟹蟹学校","蟹窝")
s2=School("猪猪学校","猪窝")
t1= Teacher("大番薯",18,30000,s1) #给大番薯传入s1学校实例
print(t1.school.name)
print(t1.school.addr)
t1.school.classes()
>>>
蟹蟹学校
蟹窝
到蟹蟹学校该班级上课
类可以做为列表的元素,字典的key,value等传入
#coding:utf-8
class UserInfo:
pass
class Department:
pass
class StartCofig:
def __init__(self,num):
self.num=num
def changeList(self,requests):
print(self.num,requests)
def run(self):
self.changeList(999)
class RoleCofig(StartCofig):
def changeList(self,requests):
print("666666666ROle")
class AdminSite:
def __init__(self):
self._registry ={}
def register(self,k,v):
self._registry[k] =v(k)
site1= AdminSite()
site1.register(UserInfo,StartCofig)
site1.register(Department,StartCofig)
print(len(site1._registry))
for k,row in site1._registry.items():
row.run()
反射
根据字符串的形式去某个对象中操作他的成员
基本用法
class Teacher:
def __init__(self,full_name):
self.full_name =full_name
t=Teacher('Egon Lin')
# hasattr(object,'name')
hasattr(t,'full_name') # 按字符串'full_name'判断有无属性t.full_name
# getattr(object, 'name', default=None)
getattr(t,'full_name',None) # 等同于t.full_name,不存在该属性则返回默认值None
# setattr(x, 'y', v)
setattr(t,'age',18) # 等同于t.age=18
# delattr(x, 'y')
delattr(t,'age') # 等同于del t.age
获取方法名后,在进行调用
class Person(object):
def __init__(self,name,age):
self.name = name
self.age =age
def aaa(self):
print("干他")
p1 = Person('egon',19)
res1 = getattr(p1,'name')
print(res1)
res2 = getattr(p1,'aaa')
res2()
>>>
egon
干他
getattr
和getattr()的区别:getattr()直接获取,如果没有该方法或者没有该属性,会直接报错。所以,使用是通常通常配合hasattr()先判断是否有该方法,然后进行使用。且无法进行定制化操作
例子:
class Frob():
pass
f = Frob()
print(getattr(f,'bn'))
>>>
AttributeError: 'Frob' object has no attribute 'bn'
getattr():当用户试图访问不存在的属性时调用,你可以通过这个魔法方法来定义类的行为。和getattr()的区别就在于可以自定义无属性时候的操作
例如:
class Frob():
def __getattr__(self, item):
print("自定骚操作,干啥都行")
return None
f = Frob()
print(f.nb)
在看一个比较有意思的例子:
class List:
def __init__(self,seq):
self.seq=seq
def append(self, p_object):
' 派生自己的append加上类型检查,覆盖原有的append'
if not isinstance(p_object,int):
raise TypeError('must be int')
self.seq.append(p_object)
@property
def mid(self):
'新增自己的方法'
index=len(self.seq)//2
return self.seq[index]
def __getattr__(self, item):
print(item) ##item是调用的方法名,只有在没有的时候才会触发
print(self.seq) ##传入的列表
return getattr(self.seq,item)
def __str__(self):
return str(self.seq)
l=List([1,2,3])
l.insert(0,-123)
print(l)
例子解释:自定义的List类,传入的列表[1,2,3],实例化出l并且调用了该类没有的insert方法,如果没有getattr会直接报错,没有该方法,Pycharm里面也会飘黄,加了getattr_后,里面使用getattr()方法找到了 self.seq列表 内置方法的insert()方法,完成了切片!!!
判断是否有方法在进行调用
class Ftp:
def put(self):
print("Download now")
def get(self):
print('pull documents')
def interaction(self):
method_ftp = input(">>>: ").strip()
if hasattr(self,method_ftp):
getattr(self,method_ftp)()
else:
print("wrong ")
obj=Ftp()
obj.interaction()
>>>
>>>: ssss
wrong
通过模块名称调用里面的类
import sys
wahaha = "娃哈哈"
def aaa():
print("aaaa")
class Vvs:
def bbb(self):
print("我是bbb")
print(sys.modules['test_base'])
print(getattr(sys.modules['test_base'],'Wechat')) ##这样就拿到了模块test_base里面的Whechat类
print(getattr(sys.modules['__main__'],'wahaha')) ##获取当前模块的wahaha属性
print(getattr(sys.modules['__main__'],'aaa')) ##这获取当前模块aaa方法
print(getattr(sys.modules['__main__'],'Vvs')) ##这获取当前模块Vvs类
b123 =getattr(sys.modules['__main__'],'Vvs')()
b123.bbb()
反射的应用
class Course:
def __init__(self,name,price,period):
self.name = name
self.price = price
self.period = period
class Student:
func_list= [
{'text':'选课','option_name':'select_course','param_key':None},
{'text':'查看课程','option_name':'show_select_course','param_key':None},
{'text':'删除课程','option_name':'del_select_course','param_key':None}
]
def __init__(self,name):
self.name = name
self.course =[]
def select_course(self,cls):
pass
def show_select_course(self,cls):
for k,v in enumerate(cls):
print(k,(v.name,v.price,v.period))
def del_select_course(self,cls):
pass
def run():
total_course_list = []
for i in range(1,3):
obj= Course(f"{i}语文课",90,9000) ##生成3门课程传入
total_course_list.append(obj)
student_info = input("请输入学生姓名:")
print(student_info)
stu= Student(student_info) #学生类实例化
for i,item in enumerate(stu.func_list,1): #打印课程论列表,和自动生成课程序号
print(i,item['text'])
while True:
num = int(input("请选择序号:")) #输入课程序号
num= num -1 #拿到序号
row = stu.func_list[num] #从func_list列表里根据index取操作的列表
name = row.get('option_name') #在操作列表里 获取对应的操作名
func = getattr(stu,name) #通过反射,在stu类里面找到对应的方法
func(total_course_list) #在该方法下传入参数
if __name__=='__main__':
run()
选课系统反射应用
#coding:utf-8
import pickle
import logging
import sys
LOGPATH = r'选课系统\operation.log'
class Course(object):
def __init__(self, name, price, period):
self.name = name
self.price = price
self.period = period
class Student(object):
opt_list = [('查看课程', 'show_courses'), ('选择课程', 'choose_course'),
('查看以选择课程', 'show_selected'), ('退出', 'exit')]
def __init__(self, name):
self.name = name
self.classes = []
def show_courses(self):
pass
def choose_course(self):
pass
def show_selected(self):
pass
def exit(self):
pass
@staticmethod
def create_obj(ret, logger):
with open('stuinfo', 'rb') as f:
while True:
try:
stu = pickle.load(f)
if stu.name == ret[0]:
obj = stu
return obj
except:
logger.error(f'学生{stu.name}查无此人信息,请检查{STUINFOPATH}')
class Manager(object):
opt_list = [('创建课程', 'create_course'), ('创建学生', 'create_student'),
('查看课程', 'show_courses'), ('查看学生', 'show_students'),
('查看学生和已选课程', 'show_stu_course'), ('退出', 'exit')]
def __init__(self, name, logger):
self.name = name
self.logger = logger
def create_course(self):
pass
def create_student(self):
user = input('usename: ')
pwd = '1234'
stu = Student(user)
with open('userinfo', mode='a', encoding='utf-8') as f:
print(f'{user}|{pwd}|Student', file=f)
with open('stuinfo', mode='ab') as f:
pickle.dump(stu, f)
self.logger.info(f'管理员{self.name}创建学生{user}')
def show_courses(self):
pass
def show_students(self):
pass
def show_stu_course(self):
pass
def exit(self):
pass
@classmethod
def create_obj(cls, ret, logger):
return cls(ret[0], logger)
def login():
'''
None
:return: 登陆成功,返回用户名和身份;否则,返回false
'''
username = input('username:')
password = input('password:')
with open('userinfo',encoding='utf-8') as f:
for line in f:
user, pwd, ident = line.strip().split('|')
if username == user and password == pwd:
return username, ident
return False
def initLog():
fh = logging.FileHandler(filename=LOGPATH, mode='a', encoding='utf-8')
ch = logging.StreamHandler()
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
fh.setFormatter(formatter)
ch.setFormatter(formatter)
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)
logger.addHandler(fh)
logger.addHandler(ch)
return logger
if __name__ == '__main__':
logger = initLog()
ret = login() ##登陆权限判断,返回用户名,和用户权限组
if ret:
print(f'登录成功,{ret[0]}欢迎使用选课系统')
cls_s = getattr(sys.modules['__main__'], ret[1]) ##通过反射 获取登陆后的学生类或者管理员类
obj = cls_s.create_obj(ret, logger) #类名.creat_obj进入到对应的不同类里的creat_obj方法
for i, opt in enumerate(cls_s.opt_list, 1):
print(i, opt[0])
num = int(input('您需要选择的操作:'))
if hasattr(obj, cls_s.opt_list[num-1][1]):
getattr(obj, cls_s.opt_list[num-1][1])()
else:
print('登陆失败')
网友评论