Python 抽象篇:面向对象之高阶用法
1.检查继承
如果想要查看一个类是否是另一个类的子类,可以使用内建的issubclass函数
如果想知道已知类的基类,可以直接使用特殊特性__bases__
同时,使用isinstance方法检查一个对象是否是一个类的实例(instance)
如果想知道一个对象属于哪个类,可以使用__class__特性
2.反射
python中的反射功能是由以下四个内置函数提供:hasattr、getattr、setattr、delattr,改四个函数分别用于对对象内部执行:检查是否含有某成员、获取成员、设置成员、删除成员。
class Foo: def __init__(self,name,age): self.name=name self.age=age def show(self): return "%s-%s"%(self.name,self.age) obj=Foo('greg',18) print(obj.name) #greg b="name" print(obj.__dict__) #{'name': 'greg', 'age': 18} print(obj.__dict__['name'])#greg print(obj.__dict__[b])#greg inp=input('>>>') #去什么东西里面获取什么内容 v=getattr(obj,inp) print(v)
#反射是通过字符串的形式操作对象相关的成员。一切事物都是对象!!! sho=getattr(obj,'show') print(sho)#<bound method Foo.show of <__main__.Foo object at 0x000001E00C46CA58>> sh=sho() print(sh)#alex-18 print(hasattr(obj,'name'))#True print(hasattr(obj,'name1'))#False setattr(obj,'k1','v1') print(obj.k1) #v1 #obj.name print(delattr(obj,'name')) #NONE # obj.name
三种方式获取obj对象中的name变量指向内存中的值 “gregory”
class Foo(object): def __init__(self): self.name = 'gregory' # 不允许使用 obj.name obj = Foo() print(obj.name) print(obj.__dict__['name']) print(getattr(obj, 'name'))
3.对象的嵌套
class F1: def __init__(self): self.name="greg" class F2: def __init__(self,a): #a=f1=[name=greg] self.age=a class F3: def __init__(self,b):#b=f2=[age=name=greg] self.dd=b f1=F1()#[name=greg] f2=F2(f1)#[age=name=greg] f3=F3(f2)#[dd=[age=name=greg]] # print(f3.dd) #<__main__.F2 object at 0x00000232ACA612B0> # print(f3.dd.age) #18 print(f3.dd.age.name) #greg
4.异常(exception object)
4.1一些重要的内建异常
AttributeError 试图访问一个对象没有的树形,比如foo.x,但是foo没有属性x IOError 输入/输出异常;基本上是无法打开文件 ImportError 无法引入模块或包;基本上是路径问题或名称错误 IndentationError 语法错误(的子类) ;代码没有正确对齐 IndexError 下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5] KeyError 试图访问字典里不存在的键 KeyboardInterrupt Ctrl+C被按下 NameError 使用一个还未被赋予对象的变量 SyntaxError Python代码非法,代码不能编译(个人认为这是语法错误,写错了) TypeError 传入对象类型与要求的不符合 UnboundLocalError 试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量, 导致你以为正在访问它 ValueError 传入一个调用者不期望的值,即使值的类型是正确的
4.2 捕捉异常
try: li=[11,22] li[999] #能捕获错误 # int('d3de')#不能捕获错误 except IndexError as e: print('IndexError',e) except ValueError as e: print('ValueError',e) except Exception as e: #在python的异常中,有一个万能异常:Exception,他可以捕获任意异常 print('Exception',e) else: print('else') finally: #finally语句不管try是否发生异常,都会被执行。 print('……')
4.3 主动触发异常
try: #主动触发异常 raise Exception('不过了……') except Exception as e: print(e)
raise语句引发了一个没有任何有关错误的普通异常。
4.4 捕捉异常写到日志
def db(): # return True return False def index(): try: r=input(">>") int(r) result=db() if not result: raise Exception('数据库处理错误') except Exception as e: str_error=str(e) print(str_error) #打开文件,写错误记录日志 r=open('log','a') r.write(str_error) index()
4.5 自定义异常
class Gregerror(Exception): def __init__(self,msg): self.message=msg def __str__(self): return self.message # obj=Gregerror('xxx') # print(obj) try: raise Gregerror("我错了……") except Gregerror as e: print(e) #e对象的__str__方法,获取返回值
4.6 断言
#assert条件 print(123) assert 1==2#断言 print(456)
4.7单例模式
单利模式存在的目的是保证当前内存中仅存在单个实例,避免内存浪费。
对于Python单例模式,创建对象时不能再直接使用:obj = Foo(),而应该调用特殊的方法:obj = Foo.get_instance() 。实例如下:
class Foo: __v=None @classmethod def get_instance(cls): if cls.__v:#如果它有值 return cls.__v else: cls.__v=Foo() return cls.__v #不要再使用 类() obj=Foo.get_instance() #obj=创建的对象 print(obj) obj2=Foo.get_instance() print(obj2) obj3=Foo.get_instance() print(obj3) # <__main__.Foo object at 0x000001B5A30E10F0> # <__main__.Foo object at 0x000001B5A30E10F0> # <__main__.Foo object at 0x000001B5A30E10F0>