python019
核能来袭-反射 本节主要内容:
1.isinstance,type,issubclass
2.区分函数和方法
3.反射(重点)
一.isinstance,type,issubclass
1.issubclass:这个内置函数可以帮我们判断xxx类是yyy类型的子类
class Base: pass class Foo(Base): pass class Bar(Foo): pass print(issubclass(Bar,Foo)) #True print(issubclass(Foo,Bar)) #False print(issubclass(Bar,Base)) #True
2.type:可以帮我们判断xxx是否是xxx数据类型的
class Foo: pass obj=Foo() print(obj,type(obj)) #查看obj的类<__main__.Foo object at 0x000001D898FB82E8> <class '__main__.Foo'> class Boy: pass class Girl: pass def func(*args): #统计传进来的男生和女生分别是多少 b=0 g=0 for obj in args: if type(obj)==Boy: b+=1 elif type(obj)==Girl: g+=1 return b,g ret=func(Boy(),Girl(),Girl(),Girl(),Boy(),Girl(),Girl()) print(ret) 或者,你在进行计算的时候.先判断好要计算的数据类型必须是int或者float.这样计算才有意义. def add(a,b): if (type(a)==int or type(a)==float ) and (type(b)==int or type(b)==float): return a+b else: print("我要报错")
3.isinstance:判断xxx是yyy类型的数据.但是isinstance没有type那么准确
class Base: pass class Foo(Base): pass class Bar(Foo): pass print(isinstance(Foo(),Foo)) #True print(isinstance(Foo(),Base)) #True print(isinstance(Foo(),Bar)) #False isinstance可以判断该对象是否是xxx家族体系中的(只能往上判断)
二.区别函数和方法
def func(): pass print(func) #<function func at 0x0000022BE6C21F28> class Foo: def chi(self): print("我是吃") f=Foo() print(f.chi) #<bound method Foo.chi of <__main__.Foo object at 0x00000212A4798438>> 函数在打印的时候.显示的是function.而方法在打印的时候显示的methon class Foo: def chi(self): print("我是吃") @staticmethod def static_methon(): pass @classmethod def class_methon(cls): pass f=Foo() print(f.chi) #<bound method Foo.chi of <__main__.Foo object at 0x0000010B091A84E0>> print(Foo.chi) #<function Foo.chi at 0x000001D40E2CA9D8> print(Foo.static_methon) #<function Foo.static_methon at 0x000001E457CAAA60> print(Foo.class_methon) #<bound method Foo.class_methon of <class '__main__.Foo'>> print(f.static_methon) #<function Foo.static_methon at 0x000001FC2CC3AA60> print(f.class_methon) #<bound method Foo.class_methon of <class '__main__.Foo'>>
结论:
1.类方法,不论任何情况,都是方法.
2.静态方法,不论任何情况,都是函数.
3.实例方法,如果是实例访问就是方法.如果是你类名访问就是函数. 那如何用程序来帮我们分辨.到底是方法还是函数呢?
首先,我们要借助于types模块. 所有的方法都是MethonType的实例
所有的函数都是FunctionType的实例 from types import MethodType,FunctionType
三.反射.
首先,我们看这样⼀个需求,说有个大牛, 写了⼀堆特别牛B的代码.然后放在了⼀个py 文件里(模块),这时, 你想用这个大牛写的东西.但是呢. 你首先得知道大牛写的这些代码都是干什么用的.那就需要你把大牛写的每一个函数跑一下.摘一摘自己想用的内容. 来咱们模拟 这样的需求,首先大牛给出一个模块.
# 大牛.py # def chi(): # print("大牛一顿吃100个螃蟹") # def he(): # print("大牛一顿喝100瓶可乐") # def la(): # print("大牛不用拉") # def shui(): # print("大牛一次睡一年") # import master # from types import FunctionType # while 1: # print("""作为大牛帮你写了: # chi # he # la # shui # 等""") # gn=input("请输入你要测试的功能:") # if hasattr(master,gn): # attr=getattr(master,gn) # if isinstance(attr,FunctionType): # attr() # else: # print(attr) # class Person: # country="大清" # def chi(self): # pass # print(getattr(Person,"country")) #类中的内容可以这样动态的获取 # print(getattr(Person,"chi")) #相当于Foo.func函数 # obj=Person() # print(getattr(obj,"country")) # print(getattr(obj,"chi")) #相当于obj.func 方法
总结:getattr可以从模块中获取内容,也可以从类中获取内容,也可以从对象中获取内容.
关于反射,其实一共有4个函数:
1.hasattr(obj,str)判断obj中是否是包含str成员
2.getattr(obj,str)从obj中获取str成员
3.setattr(obj,str,value)把obj中的str成员设置成value.
注意:这里的value可以是值,也可以是函数或者方法
4.delattr(obj,str)把obj中的str成员删掉
class Foo: pass f=Foo() print(hasattr(f,"chi")) #False setattr(f,"chi","123") print(f.chi) #被添加一个属性信息 setattr(f,"chi",lambda x: x+1) print(f.chi(3)) #4 delattr(f,"chi") print(hasattr(f,"chi")) #False