反射、isinstance和issubclass
isinstance和issubclass
isinstance(obj,cls)检查是否obj是否是类 cls 的对象
print(isinstance(1,int))#输出:True print(isinstance("abc",str))#输出:True print(isinstance([],list))#输出:True #判断第一个参数是你是第二个参数的实例
class A:pass
class B(A):pass
class C(B):pass
c = C()
print(isinstance(c,B)) # 包含继承关系的判断 True
print(type(c) is B) #False
print(type(c) is A) # type只关心创建这个对象的类 False
issubclass(sub, super)检查sub类是否是 super 类的派生类
class A:pass class B(A):pass print(issubclass(A,B)) #False print(issubclass(B,A)) #True # 第一个参数是疑似子类,第二个参数是疑似父类. # 最终结果如果真的是父子类关系,则返回True
反射
1 什么是反射
反射的定义 : 通过字符串 来 操作python代码中的 变量 函数 甚至类和方法
2 python面向对象中的反射:通过字符串的形式操作对象相关的属性。python中的一切事物都是对象(都可以使用反射)
四个可以实现自省的函数
下列方法适用于类和对象(一切皆对象,类本身也是一个对象)
getattr()、hasattr()、setattr()、delattr()
反射静态方法:
class A: name = 'alex' # 静态 属性 age = 83 # 静态 属性 print(getattr(A,'name')) #可以直接操作字符串 输出:alex #如果第二个参数没有,会报错,所有先用hasattr 判断 print(hasattr(A,'name')) #输出:True tag=input(">>>") if hasattr(A,tag): #先判断,再getattr()避免报错 print(getattr(A,tag)
#用字符串调用方法 class Student: def __init__(self,name,age): self.name = name self.age = age def show(self): for key in self.__dict__: print(key,self.__dict__[key]) lin=Student("liulin",123) print(hasattr(lin,"show")) #True 证明实例化的这个对象里面有show方法 print(getattr(lin,"show")) #输出方法的内存地址,想调用后面加() f=getattr(lin,"show") f()# 输出:name liulin # age 123
setattr()增改操作
class Student: def __init__(self,name,age): self.name = name self.age = age def show(self): for key in self.__dict__: print(key,self.__dict__[key]) hei = Student('小黑',18) hei.show() hei.sex = '男' #正常方法加一个属性 setattr(hei,'sex','不详') # setattr方法实现字符串对类的增改操作,三个参数(对象,属性,属性值) print(hei.sex)
delattr()删除操作
delattr(hei,'sex') # 删除操作 print(hei.__dict__)
小结:
hasattr 判断某一个 变量 是否能够.调用一个名字,返回True或者False
getattr 直接获取一个变量中的名字的值
setattr 为一个变量增加或者修改一个属性 三个参数:setattr(对象,属性,属性值)
delattr 删除一个变量中的属性或者方法
操作模块:
import my_moudle #引用模块 print(my_moudle.money) print(getattr(my_moudle,'money')) #用字符串执行模块的属性 getattr(my_moudle,'qqxing')() #用字符串执行模块的方法
反射当前模块
sys.modules[“__main__"] :找到当前模块
由于__main__在一个py文件里被其他py文件作为模块导入,则__main__值会发生改变,所以用__name__,保持原来的值
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import sys # print(sys.modules[__name__]) # 一定是当前.py # print(sys.modules['__main__']) # 不确定的,导到哪,就是哪的py # print(getattr(sys.modules[__name__],'count')) # getattr(sys.modules[__name__],'sww')() # print(sys.modules[__name__]) # # print(sys.modules['my_moudle']) # # print(my_moudle) # print(getattr(sys.modules['my_moudle'],'qqxing'))
一共四种反射情况:
反射类中的名字 getattr(类名,'静态属性') getattr(类名,'类方法')() getattr(类名,'静态方法')() 反射对象中的名字 getattr(对象名,'对象属性') getattr(对象名,'方法名')() 反射模块中的名字 import 模块名 getattr(模块名,'模块中的变量') getattr(模块名,'模块中的函数')() getattr(模块名,'模块中的类名') 反射当前模块中的名字 import sys getattr(sys.modules[__name__],'变量') getattr(sys.modules[__name__],'函数')() getattr(sys.modules[__name__],'类名')
反射类:
class Student: def __init__(self,name,age): self.name = name self.age = age def show_student(self): for key in self.__dict__: print(key,self.__dict__[key])