核能来袭-反射 本节主要内容:
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("我要报错")
View Code
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 方法
View Code
总结: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