主要内容:
- isinstance, type, issubclass( 内置函数)
- 区分函数和方法
- 反射
一 ( isinstance, type, issubclass)
- isinstance() :可以帮我们判断xx类是否是xx类的子类.
class Basse: pass class Foo: pass
lass Bar(Foo): pass print(issubclass(Bar,Foo)) #true print(issubclass(Foo,Bar)) #false print(issubclass(Bar,Basse)) # False
2. type() : 表示查看obj是由哪个类创建的
class Foo: pass obj = Foo() print( obj,type(obj)) # 查看obj的类 <__main__.Foo object at 0x0000019D93228198> <class '__main__.Foo'>
判断好要计算的数据类型必须是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是YY类型的数据.但是它没有type那么精准.
lass Animal: pass class Cat(Animal): pass class BoSiCat(Cat): pass # a = Animal() # print(isinstance(a, Animal)) # 自己类可以判断 # print(isinstance(a, Cat)) # 子类不能判断 c = BoSiCat() print(isinstance(c, Animal)) # True 子类的对象可以当成父类的类型来看.
isinstance 可以判断对象是否是xxx家族体系中的(只能往上判断)
二 区分函数和方法
我们可以直接用打印来看结果
例子
class Foo: def chi(self): print("我是吃") @staticmethod def static_method(): pass @classmethod def class_method(cls): pass f=Foo() print(f.chi) # <bound method Foo.chi of <__main__.Foo object at 0x0000023453028588>>
print(Foo.chi) #<function Foo.chi at 0x000001AFE215A950
print(f.static_method) # 拿对象来访问function Foo.static_method at 0x0000022A951AA9D8> print(Foo.static_method) # 拿类来访问<function Foo.static_method at 0x0000014459E4A9D8> print(f.class_method) #<bound method Foo.class_method of <class '__main__.Foo'>> print(Foo.class_method) #那类来访问 <bound method Foo.class_method of <class '__main__.Foo'>>
结论: 类方法: 无论任何情况都是方法
静态方法:无论任何情况都是函数
实例方法: 如果是实力访问就是方法,如果是类名访问就是函数
那如何用程序来帮我们分辨到底是函数换是方法呢?
例子:
首先我们要借助typrs模块
# 所有的方法都是Method的实例 #所有的函数都是functiontypes的实例 from types import MethodType,FunctionType #引入模块 def func(): pass print(isinstance(func,FunctionType)) #true print(isinstance(func,MethodType)) # false class Foo: def chi(self): print("我是吃") @staticmethod def static_method(): pass @classmethod def class_method(cls): pass obj=Foo() print() print(type(obj.chi)) # method print(type(Foo.chi)) # function # print(isinstance(obj.chi, MethodType)) # True # print(isinstance(Foo.chi, FunctionType)) # True # # print(isinstance(Foo.static_method, FunctionType)) # True # print(isinstance(Foo.static_method, MethodType)) # False # # print(isinstance(Foo.class_method, FunctionType)) # False # print(isinstance(Foo.class_method, MethodType)) #true
三 反射
import fanshe # 引入模块 from types import FunctionType # while 1: # print('''大牛写的功能 # chi # he # la # shui # 调试哪个''') # ts=input("请输入你要调试的功能") # if ts=='chi': # fanshe.chi() # elif ts=="he": # fanshe.he() # elif ts=="la": # fanshe.la() # elif ts=='shui': # fanshe.shui() # else: # print("大牛没有这个功能") #写是写完了. 但是.....如果大牛现在写了了100个功能呢? 你的判断要判断100次么? # 我们可以使用反射来完成这样的功能. 非常的简单. 想想. 这里我们是不是让用户输入要执行的功能了. 那这个功能就是对应 # 模块里的功能. 那也就是说. 如果能通过字符串来动态访问模块中的功能就能解决这个问题 #例子2 # while 1: # print('''大牛写的功能 # chi # he # la # shui # 调试哪个''') # ts=input("请输入你要调试的功能") # func=getattr(fanshe,ts) # geattr (对象,字符串)从对象中获取到xxx功能,此时xxx表示一个字符串,get # #表示找,attr表示属性功能 # func() ## 写完了 但是这样有个问题在大牛的代码里没有你要找的内容,这时侯就会报错,所以在获取attr之前,要先判断下 #有没有这个功能 # 看下完整代码: # while 1: # print('''大牛写的功能 # chi # he # la # shui # 调试哪个''') # ts = input("请输入你要调试的功能") # if getattr(fanshe, ts): #如果fanshe里有你要的功能 # # 获取这个功能,并执行 # attr=getattr(fanshe,ts) # if isinstance(attr,FunctionType): #判断是否是函数,只有函数才可以被调用 # attr() # else: #如果不是就打印 # print(attr) # 两个函数 getattr():来获取信息 从对象中获取xxx功能 # hasattr()用来判断xxx中是否包含了xxx功能 # class person: # cuontry="daqing" # 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可以从模块中获取也可以从类中获取,也可以从类中获取.在python中一切皆对象 # 那可以这样认为.getattr从对象中动态获取成员. #来看个例子: class person: def cih(self): print("吃") def he(self): print("和") def la(self): print("啦") def sa(self): print("sa") def shui(self): print("睡") def run(self): lst=['chi','he','la','sa','shui'] num = int(input("""本系统有以下功能 1. 吃 2. 喝喝 3. 拉 4. 撒 5. 睡 请选择你要执⾏行行的功能:""")) # func = getattr(Person, lst[num - 1]) # func(self) # 通过对象来访问更更加合理理 # method = getattr(self, lst[num-1]) # method() p=person() p.run() # 补充: # 关于反射, 其实一共有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成员删除掉 # 注意, 以上操作都是在内存中进行的. 并不会影响你的源代码 #setarrt 例子1 # 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 ## setarrt 例子2 class Person: def __init__(self, name): self.name = name self.age = None def chi(self): print("人喜欢吃东西%s" % self.name) p = Person("刘伟") setattr(p, "name", "大阳哥") # 动态的给对象设置属性和值 setattr(p, "age", 18) # 很少用. 慎用 print(p.age) delattr(p, "age") print(p.age) # p.chi() # val = input("请输入你想让刘伟执行的动作:") # if hasattr(p, val): # getattr(p, "name") # func = getattr(p, val) # func()