面向对象进阶(一)
一 isinstance(obj,cls)和issubclass(sub,super)
isinstance(obj,cls)检查是否obj是否是类 cls 的对象
class Foo(object): pass obj = Foo() isinstance(obj, Foo)
issubclass(sub, super)检查sub类是否是 super 类的派生类
class Foo(object): pass class Bar(Foo): pass issubclass(Bar, Foo)
二 反射
一 python面向对象中的反射:通过字符串的形式操作对象相关的属性。python中的一切事物都是对象(都可以使用反射)
四个可以实现自省的函数
下列方法适用于类和对象(一切皆对象,类本身也是一个对象)
1、hasattr #判断属性有没有
class People: country='China' def __init__(self,name): self.name=name p=People('egon') print(hasattr(p,'name')) print(hasattr(People,'country')) #People.country print(hasattr(People,'__init__')) #People.__init__
2、getattr #检查是否能拿到属性,有返回值
class People:
country='China'
def __init__(self,name):
self.name=name
def walk(self):
print('%s is walking' %self.name)
p=People('egon')
res=getattr(p,'country') #res=p.country print(res) f=getattr(p,'walk') #t=p.walk print(f) f1=getattr(People,'walk') print(f1)
print(getattr(p,'xxxxxxxx','这个属性确实不存在'))
#结果输出:这个属性确实不存在
#保证程序的正常运行
hasattr getattr 应用
if hasattr(p,'walk'):#先判断属性是否存在 func=getattr(p,'walk')#然后拿到属性执行 func()
3、setattr #设置属性
class People:
country='China'
def __init__(self,name):
self.name=name
p=People('egon')
setattr(p,'age',18) print(p.__dict__) print(p.age)
4、delattr 删除属性
class People:
country='China'
def __init__(self,name):
self.name=name
p=People('egon')
print(p.__dict__)
delattr(p,'name')
print(p.__dict__)
二、反射当前模块的属性
在test文件中
import sys #导入模块,可以将这个文件作为个模块实例化 class Foo: pass def s1(): print('s1') def s2(): print('s2') 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)
在test2文件中
import test #将test作为模块导入 print(test) print(test.x) #调用test模块内的属性print(test.s1)print(test.s2)
反射的应用
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()
三 为什么用反射之反射的好处
好处一:实现可插拔机制
class FtpClient: 'ftp客户端,但是还么有实现具体的功能' def __init__(self,addr): print('正在连接服务器[%s]' %addr) self.addr=addr
import FtpClient f1=FtpClient('192.168.1.1') if hasattr(f1,'get'): func_get=getattr(f1,'get') func_get() else: print('---->不存在此方法') print('处理其他的逻辑')
好处二:动态导入模块(基于反射当前模块成员)
通过字符串导入模块
# m=input("请输入你要导入的模块:") # m1=__import__(m) # print(m1) # print(m1.time()) #推荐使用方法 import importlib t=importlib.import_module('time') print(t.time())
三 __setattr__,__delattr__,__getattr__
1.__setattr__ 添加/修改属性会触发它的执行
2.__delattr__ 删除属性的时候会触发
3.__getattr__ 只有在调用属性且不存在的时候才会触发
class Foo: x=1 def __init__(self,y): self.y=y def __getattr__(self, item): print('----> from getattr:你找的属性不存在') def __setattr__(self, key, value): print('----> from setattr') # self.key=value #这就无限递归了,你好好想想 self.__dict__[key]=value #应该使用它 def __delattr__(self, item): print('----> from delattr') # del self.item #无限递归了 self.__dict__.pop(item) #__setattr__添加/修改属性会触发它的执行 f1=Foo(10) print(f1.__dict__) # 因为你重写了__setattr__,凡是赋值操作都会触发它的运行,你啥都没写,就是根本没赋值,除非你直接操作属性字典,否则永远无法赋值 f1.z=3 print(f1.__dict__) #__delattr__删除属性的时候会触发 f1.__dict__['a']=3#我们可以直接修改属性字典,来完成添加/修改属性的操作 del f1.a print(f1.__dict__) #__getattr__只有在使用点调用属性且属性不存在的时候才会触发 f1.xxxxxx
###
----> from setattr
{'y': 10}
----> from setattr
{'y': 10, 'z': 3}
----> from delattr
{'y': 10, 'z': 3}
----> from getattr:你找的属性不存在
四 二次加工标准类型(包装)
包装:python为大家提供了标准数据类型,以及丰富的内置方法,其实在很多场景下我们都需要基于标准数据类型来定制我们自己的数据类型,新增/改写方法,这就用到了继承/派生。
授权:授权是包装的一个特性, 包装一个类型通常是对已存在的类型的一些定制,这种做法可以新建,修改或删除原有产品的功能。其它的则保持原样。授权的过程,即是所有更新的功能都是由新类的某部分来处理,但已存在的功能就授权给对象的默认属性。(不能用继承来实现时)
class List(list): def append(self, p_object): if not isinstance(p_object,int): raise TypeError('must be int') super().append(p_object) def insert(self, index, p_object): if not isinstance(p_object,int): raise TypeError('must be int') super().insert(index,p_object) l=List([1,2,3]) print(l) l.append(4) print(l) l.append('5') print(l)
class Open: def __init__(self,filepath,m='r',encode='utf-8'): self.x=open(filepath,mode=m,encoding=encode)#给open功能授权 self.filepath=filepath self.mode=m self.encoding=encode def write(self,line): t=time.strftime('%Y-%m-%d %X') self.x.write('%s %s' %(t,line)) def __getattr__(self, item): return getattr(self.x,item) f=Open('b.txt','w') f.write('111111\n') f.write('111111\n') f=Open('b.txt','r+') print(f.read) res=f.read() #self.x.read() print(res) f.seek(0) print(f.read())

浙公网安备 33010602011771号