1. isinstance(obj,cls) ----查看obj是否为cls的对象;
issubclass(sub,super)------查看sub是否为super的子类
class A(): pass a=A() print(isinstance(a,A)) # instance(obj,cls)查看obj是否为cls的对象 class B(A): pass print(issubclass(B,A)) # issubclass(sub,super)查看sub是否为super的子类
反射----根据变量的字符串形式获得变量的值;
1.反射对象的属性 VS 反射对象的方法
class Student(): def __init__(self,name): self.name=name # 对象属性 def get_name(self): return self.name student=Student("璇璇") if hasattr(student,'name'): # 查看对象student是否含有name属性(只是这里是name属性的字符串形式) ret=getattr(student,'name') print('使用反射获得对象的属性',ret) if hasattr(student,'get_name'): ret=getattr(student,'get_name') # ret其实就是student.get_name 反射对象的方法,从对象方法的字符串形式获得该对对象的方法 print("使用反射调用对象的方法:",ret())
运行结果:
2. 反射类中的属性和方法;
class Person(): country='China' # 类属性,又叫静态属性 @classmethod # 定义类方法 def func(cls): print("这是类方法,类属性的值为:",cls.country) @staticmethod def func2(): print("这是静态方法,里面不需要传self,cls等就是放在类中的普通函数") if hasattr(Person,'country'): # 查看类中是否有country静态属性 ret=getattr(Person,'country') print("使用反射根据类中静态属性的字符串形式获得静态属性的值:",ret) if hasattr(Person,'func'): ret=getattr(Person,'func') # 使用反射根据类方法的字符串形式获得类方法ret ,ret相当于Person.func ret() if hasattr(Person,'func2'): #反射类的静态方法 ret=getattr(Person,'func2') ret()
运行结果:
3. 反射模块中的属性和方法:
首先需要导入的模块 test.py中:
# 这个模块需要被test1.py导入的,测试模块中的反射 name='xuanxuan' def func(): print("我是被导入模块test.py中的方法")
import test # 导入test模块 if hasattr(test,'name'): # 查看被导入的模块是否含有name属性,这里是name的字符串形式, ret=getattr(test,'name') # 可以使用getattr对象属性的字符串形式获得对象的属性 print("使用反射获得模块中属性的值:",ret) if hasattr(test,'func'): # 查看模块test是否含有func方法 ret=getattr(test,'func') ret()
运行结果:
4. 内置模块也可以使用反射
比如用户输入time模块的一个方法名,需要用户输出time模块中该方法,但是我们不能直接使用,因为用户输入获得的是一个字符串形式的函数名,我们需要使用getattr(模块名,字符串形式的方法名)获得该模块的该方法
import time func_name=input(">>>") if hasattr(time,func_name): # 查看time模块是否含有func_name,只不过这里收到的是字符串形式 func=getattr(time,func_name) # 比如输入localtime, func就相当于time.localtime print(func()) # 输入localtime func()相当于time.localtime()
运行结果:
5. 反射自己模块中的属性和方法
这里需要注意,当前py文件获得当前py文件(模块名)可以使用sys.modules字典中 __name__键对应的值,也即使用sys.modules[__name__]就可以获得当前的模块名(其实就是当前py文件的文件名);
import sys name='xuanxuan' def func(): return "我是当前文件中的方法" # 我们可以直接使用name,或者直接调用func()函数 print(name) print(func()) # 当然也可以使用这种方式来获得当前模块(当前py文件)的属性和方法: print(sys.modules[__name__]) # 可以打印当前模块名 print("使用sys.modules[__name__]获得当前模块名,使用这种方式调用当前模块中的属性:",sys.modules[__name__].name) # 这样也可以获得当前模块中的name变量,但是我们通常不去这样做,因为在自己的模块中就直接可以使用属性和方法 print("使用sys.modules[__name__]来获得当前模块名,然后使用模块名.方法获得当前模块中的方法:",sys.modules[__name__].func()) print("*******************接下来使用反射获得当前模块中的属性和方法,比如你在当前模块拿到的是'name'或者'func'这种字符串形式的") if hasattr(sys.modules[__name__],'name'): # 查看当前模块sys.modules[__name__]是否含有name属性 ret=getattr(sys.modules[__name__],'name') print("使用反射获得当前模块的name属性的值:",ret) if hasattr(sys.modules[__name__],'func'): # 查看当前模块是否含有方法名func ret=getattr(sys.modules[__name__],'func') print('使用反射获得当前模块的方法func:',ret())
运行结果:
6. 一个模块中的类也可以使用反射获得:
被导入模块test.py中的内容:
# 这个模块需要被test1.py导入的,测试模块中的反射 class A(): def func(self): print("我是被导入的模块中的类 中的方法")
import test if hasattr(test,'A'): # 查看导入的模块test中是否含有类A,但是有可能我们拿到的是字符串形式的'A' cls=getattr(test,'A') # cls相当于test.A其实就是类A obj=cls() # obj 其实相当于导入模块test中类A的对象 obj.func() # 可以使用类A的对象obj调用在类A中定义的方法func
运行结果:
总结:
只要是可以用 什么.什么 的形式来调用的都可以使用反射来完成通过拿到的字符串形式,获得本来的值;
setter ----设置修改属性 ; delattr----删除属性
class A(): def func(self): print("类A中的方法") setattr(A,'name','名字') # 设置类A的类属性,静态属性,这个属性依然是字符串类型的,但是实际上操作的确是不带引号的 print("类A中的name属性值:",A.name) # 类属性 a=A() setattr(a,'name','璇璇') # 设置对象的name属性 print("对象a中的name属性值:",a.name)
运行结果:
但是如果delattr删掉对象a中的name属性呢?
class A(): def func(self): print("类A中的方法") setattr(A,'name','名字') # 设置类A的类属性,静态属性,这个属性依然是字符串类型的,但是实际上操作的确是不带引号的 print("类A中的name属性值:",A.name) # 类属性 a=A() setattr(a,'name','璇璇') # 设置对象的name属性 print("对象a中的name属性值:",a.name) delattr(a,'name') # 反射中的一些方法,,操作的对象都素hi字符串类型的,我们就是想通过这些字符串类型的属性或者方法,来获得实际不带引号的属性和放啊 print("删掉对象a中的name属性之后,对象的属性没有了,但是a.name时 由对象指针会去类中去找对应的属性:",a.name)
运行结果: