反射及内置方法
知识点补充,内置函数enumerate
l = ["小明","小李","小白"] for num,i in enumerate(l,1):#后面数字的1表示索引加1 print(num,i) # 1 小明 # 2 小李 # 3 小白
isinstance() 判断对象所属类型,包括继承关系
issubclass() 判断类与类之间的继承关系
class A: pass class B(A): pass b = B() print(isinstance(b,B)) #True print(isinstance(b,A)) #True class A:pass class B(A):pass print(issubclass(B,A))#True print(issubclass(A,B))#False
什么是反射?
用字符串数据类型的变量名来访问这个变量的值
反射的方法: getattr hasattr (setattr delattr)不常用
setattr,delattr
class A: def __init__(self,name): self.name = name a = A('alex') setattr(a,'name','alex_SB') print(a.name)#alex_SB del a.name print(a.__dict__) delattr(a,"name")#{} print(a.__dict__)
反射
hasattr,getattr
类名.名字
getattr(类名,'名字')
对象名.名字
getattr(对象,'名字')
模块名.名字
import 模块
getattr(模块,'名字')
自己文件.名字
import sys
getattr(sys.modules['__main__'],'名字')
类名或者对象使用getattr方法
class Person: age = "18" def __init__(self,name): self.name = name @classmethod def work(cls): return cls.age @staticmethod def pp(): return "oo" p = Person("1") print(getattr(p,"work")()) #getattr(方法名或者类名,字符串类型的属性名或者方法名)执行方法后面加() print(getattr(p,"pp")()) print(getattr(p,"age")) num = input("请输入") if hasattr(p,num):#如果类或对象里面有这个属性或方法 getattr(p,num)()#则查看这个属性或者执行这个方法 else: print("shabi")#否则返回你要让他返回的内容
用系统模块和自己创建的模块使用getattr方法
import os # os.rename("课程","白痴") getattr(os,"rename")("白痴","课程")#getattr(模块名,字符串类型方法名) import sys def oo(): print("哦哦") getattr(sys.modules["__main__"],"oo")()
反射的应用,选课系统
# 选课系统的代码 # login # 判断身份 并且根据身份实例化 # 根据每个身份对应的类 让用户选择能够做的事情 class Manager: OPERATE_DIC = [ ('创造学生账号', 'create_student'), ('创建课程','create_course'), ('查看学生信息','check_student_info'), ] def __init__(self,name): self.name = name def create_student(self): print('创建学生账号') def create_course(self): print('创建课程') def check_student_info(self): print('查看学生信息') class Student: OPERATE_DIC = [ ('查看所有课程', 'check_course'), ('选择课程', 'choose_course'), ('查看已选择的课程', 'choosed_course') ] def __init__(self,name): self.name = name def check_course(self): print('check_course') def choose_course(self): print('choose_course') def choosed_course(self): print('查看已选择的课程') def login(): username = input('user : ') password = input('pwd : ') with open('userinfo') as f: for line in f: user,pwd,id = line.strip().split('|') # ident = 'Manager' if user == username and pwd == password: print('登录成功') return username,id import sys def main(): usr,id = login() print('user,id :',usr,id) cls = getattr(sys.modules['__main__'],id) #Manager = getattr(当前文件,'Manager') obj = cls(usr) operate_dic = cls.OPERATE_DIC while True: for num,i in enumerate(operate_dic,1): print(num,i[0]) choice = int(input('num >>>')) choice_item = operate_dic[choice-1] getattr(obj,choice_item[1])()
内置方法
__call__ 相当于 对象()
class Student: def __call__(self, *args, **kwargs): print("oo") s = Student() s()#直接执行__call__方法
__len__ len(obj)
class Student: def __init__(self,name): self.name = name def __len__(self): return len(self.name) s = Student("我是大帅哥") print(len(s))#直接执行__len__方法,输出5
__new__ 特别重要 开辟内存空间的 类的构造方法,写一个单例类
class Person: def __new__(cls, *args, **kwargs): s = object.__new__(cls) return s#返回那个空间 def __init__(self,name): self.name = name p = Person()#再实例化对象的时候执行__new__方法,开辟空间 单例类 class Person: __age = None def __new__(cls, *args, **kwargs): if not cls.__age:#如果有空间,就不重新开辟空间 cls.__age = object.__new__(cls) return cls.__age def __init__(self,name): self.name = name p = Person("小明") p2 = Person("小李") print(p.name) print(p2.name)#实例化的对象都在第一次开辟的空间里,后面实例化的对象属性也覆盖前面的对象属性,都输出小李
__str__ str(obj),'%s'%obj,print(obj)
class A: def __str__(self): return ("%s,%s,%s" % (self.name,self.age,self.sex)) def __init__(self,name,age,sex): self.name = name self.age = age self.sex = sex a = A("小明","18","男") print(str(a)) print(a) print("%s"%a)#三个输出结果一样,都自动执行__str__方法