一 isinstance(obj,cls)和issubclass(sub,super)
isinstance(obj,cls)检查是否obj是否是类 cls 的对象
class Foo: pass obj = Foo() print(isinstance(obj,Foo))
issubclass(sub, super)检查sub类是否是 super 类的派生类
class Foo: pass class Bar(Foo): pass print(issubclass(Bar,Foo))
二 反射
1、什么是反射
主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)。
2、python面向对象中的反射:通过字符串的形式操作对象相关的属性。python中的一切事物都是对象(都可以使用反射)
- 基于对象级别的反射
- 基于类级别的反射
- 基于模块级别的反射
四个可以实现自省的函数:
def hasattr(*args, **kwargs): # real signature unknown """ Return whether the object has an attribute with the given name. This is done by calling getattr(obj, name) and catching AttributeError. """ pass #检测是否含有某属性
def getattr(object, name, default=None): # known special case of getattr """ getattr(object, name[, default]) -> value Get a named attribute from an object; getattr(x, 'y') is equivalent to x.y. When a default argument is given, it is returned when the attribute doesn't exist; without it, an exception is raised in that case. """ pass #获取属性
def setattr(x, y, v): # real signature unknown; restored from __doc__ """ Sets the named attribute on the given object to the specified value. setattr(x, 'y', v) is equivalent to ``x.y = v'' """ pass #设置属性
def delattr(x, y): # real signature unknown; restored from __doc__ """ Deletes the named attribute from the given object. delattr(x, 'y') is equivalent to ``del x.y'' """ pass #删除属性
使用演示:
class People: country='China' def __init__(self,name): self.name=name def walk(self): print('%s is walking'%self.name) p=People('egon') print(People.__dict__) print(p.name) print(p.__dict__) #---------------------- #hasattr print('name' in p.__dict__) print(hasattr(p,'name')) print(hasattr(p,'name1213')) print(hasattr(p,'country')) #p.country #基于对象 print(hasattr(People,'country')) #People.country #基于类 print(hasattr(People,'__init__')) #People.__init__ #---------------------- #getattr res=getattr(p,'country') #res=p.country print(res) f=getattr(p,'walk') #t=p.walk print(f) f1=getattr(People,'walk') print(f1) f() f1(p) print(p.xxxxxxx) print(getattr(p,'xxxxxxxx','这个属性确实不存在')) if hasattr(p,'walk'): func=getattr(p,'walk') func() print('================>') print('================>') #---------------------- #setattr p.sex='male' print(p.sex) print(p.__dict__) setattr(p,'age',18) print(p.__dict__) print(p.age) print(getattr(p,'age'))
#反射当前模块的属性 import sys x=1111 class Foo: pass def s1(): print('s1') def s2(): print('s2') # print(__name__) this_module = sys.modules[__name__] print(this_module) print(hasattr(this_module, 's1')) print(getattr(this_module, 's2')) print(this_module.s2) print(this_module.s1)
模块补充:
__name__可以区别文件的用途:
- 一种用途是直接运行文件,这叫把文件当成脚本运行。
- 一种用途是不运行文件,在另一个文件中导入这个模块。
3、反射的用途
import sys def add(): print('add') def change(): print('change') def search(): print('search') def delete(): print('delete') func_dic={ 'add':add, 'change':change, 'search':search, 'delete':delete } while True: cmd=input('>>:').strip() if not cmd:continue if cmd in func_dic: #hasattr() func=func_dic.get(cmd) #func=getattr() func()
import sys def add(): print('add') def change(): print('change') def search(): print('search') def delete(): print('delete') this_module=sys.modules[__name__] while True: cmd=input('>>:').strip() if not cmd:continue if hasattr(this_module,cmd): func=getattr(this_module,cmd) func()
好处一:实现可插拔机制
反射的好处就是,可以事先定义好接口,接口只有在被完成后才会真正执行,这实现了即插即用,这其实是一种‘后期绑定’,什么意思?即你可以事先把主要的逻辑写好(只定义接口),然后后期再去实现接口的功能
模拟FTP功能:
class FtpClient: 'ftp客户端,但是还么有实现具体的功能' def __init__(self,addr): print('正在连接服务器[%s]' %addr) self.addr=addr def test(self): print('test') def get(self): print('get------->')
import ftpclient # print(ftpclient) # print(ftpclient.FtpClient) # obj=ftpclient.FtpClient('192.168.1.3') # print(obj) # obj.test() f1=ftpclient.FtpClient('192.168.1.1') if hasattr(f1,'get'): func=getattr(f1,'get') func() else: print('-->不存在此方法') print('其他逻辑')
好处二:动态导入模块(基于反射当前模块)
# m=input("请输入你要导入的模块:") # m1=__import__(m) # print(m1) # print(m1.time()) #推荐使用方法 import importlib t=importlib.import_module('time') print(t.time())