python 之 面向对象(三)
isinstance 和 issubclass
class Foo: pass class Son(Foo): pass s =Son() #判断一个对象是不是这个类的对象,传两个参数(对象,类) print(isinstance (s,Son)) print(isinstance (s,Foo)) print(type(s) is Son)#Ture print(type(s) is Foo)#False #isinstance he type 的区别,type可以做精准判断 #判断一个类是不是另一个类的子类 print(issubclass(Son,Foo)) print(issubclass(Son,object)) print(issubclass(Foo,object)) print(issubclass(int,object)) python 中所有类的父类都是object
反射
什么是反射
反射主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)
python面向对象中的反射:通过字符串的形式操作对象相关的属性。python中的一切事物都是对象(都可以使用反射)
四个可以实现自省的函数
hasattr getattr setattr delattr
class Foo: def __init__(self): self.name = "egon" self.age = 73 def func(self): print(123) egg = Foo() edd = Foo() #常用的hasattr #常用的getattr # print(hasattr(egg,'name'))#True # print(getattr(egg,'name'))#egon #先通过hasattr判断里面有没有,再用getattr取出来 # if hasattr(egg,'func'):#如果存在返回属性值或者方法的内存地址,不存在报错 # q = getattr(egg,'func')#这两种方法常一起结合使用 # q() #不常用 # setattr # setattr(egg,'sex','male') # print(egg.sex) def show_name(self): print( self.name+"sb") setattr(egg,'sh_name',show_name) egg.sh_name(egg) show_name(egg) egg.sh_name#这里是需要传参数的
#delattr
#delattr(egg,'name')
#print(egg.name)
class Foo: f = '类的静态变量' def __init__(self,name,age): self.name = name self.age = age def say_hi(self): print('hi,%s'%self.name) obj = Foo('egon',73) #检查是否含有某属性,返回布尔值 # print(hasattr(obj,'name')) # print(hasattr(obj,'say_hi')) #获取属性 # n = getattr(obj,'name') # print(n) # func = getattr(obj,'say_hi') # func() # print(getattr(obj,'www','没有'))#报错,这里的getattr有一个默认参数default可以赊着 #设置属性 setattr(obj,'sb',True) setattr(obj,'show_name',lambda self:self.name+'sb') print(obj.__dict__) print(obj.show_name(obj)) #删除属性 delattr(obj,'age') delattr(obj,'show_name') print(obj.__dict__) # delattr(obj,'show_name111')#不存在会报错
class Foo(object): staticField = 'old boy' def __init__(self): self.name = "wupeiqi" def func(self): return 'func' @staticmethod def bar(): return 'bar' print(Foo.bar()) print(getattr(Foo,'staticField')) print(getattr(Foo,'func')) print(getattr(Foo,'bar'))
import sys def s1(): print('s1') def s2(): print('s2') this_module = sys.modules[__name__]#查看当前模块 print(hasattr(this_module,'s1')) print(getattr(this_module,'s2'))
导入其它模块,利用反射查找该模块是否存在某个方法
def test(): print('from the test')
'''程序目录: my_module.py 随笔.py 当前文件: 随笔.py''' import my_module as obj #obj.test() print(hasattr(obj,'test')) getattr(obj,'test')()
内置方法
__str__ 和__repr__
改变对象的字符串显示__str__, __repr__
自定制格式化字符串__format__
class School: def __init__(self,name,addr,type): self.name = name self.addr = addr self.type = type def __str__(self): return 'School2(%s,%s)' % (self.name, self.addr) def __repr__(self): return 'School1(%s,%s)'%(self.name,self.addr) def __format__(self,format_spec): if not format_spec or format_spec not in format_dic: format_spec = 'tna' fmt = format_dic[format_spec] return fmt.format(obj =self) s1 = School('oldboy1','北京','私立') print('from %r'%s1) print('from %s'%s1) print(s1) ''' str函数或者print函数---->obj.__str__() repr或者交互解释器---->obj.repr__() 如果__str__没有被定义,那么就会使用__repr__来代替输入 注意:这俩方法的返回值必须是字符串,否则抛出异常 ''' print(format(s1,'nat')) print(format(s1,"tna")) print(format(s1,"tan")) print(format(s1,"asfdasdffd")) '''当打印一个对象的时候,如果实现了str,打印str中的返回值 当str没有被实现的时候,就会调用repr方法 但是当你用字符串格式化的时候 %s和%r会分别去调用__str__和__repr__ 不管是在字符串格式化的时候还是在打印对象的时候,repr方法都可以作为str方法的替补 但反之不行 用于友好的表示对象。如果str和repr方法你只能实现一个:先实现repr '''
__del__
析构方法,当对象在内存中释放时,会自动触发执行。
执行del 方法时调用__del__
注:构析函数的调用是由解释器在进行垃圾回收自动触发执行的
class Foo: def __del__(self): print('执行我啦') f = Foo() print(123) print(123) try:#使用try处理一下 del f print(f)#NameError: name 'f' is not defined except NameError as e: print("name f 已经被删除了") finally: print(123)
item系列
__getitem__ __setitem__ __delitem__
class Foo: def __init__(self): self.name = 'egon' self.age = 73 def __getitem__(self, item): return self.__dict__[item] def __setitem__(self, key, value): self.__dict__[key] = value def __delitem__(self, key): del self.__dict__[key] f = Foo() print(f['name'])#egon f['name'] = 'alex' print(f.name)#alex del f['name'] print(f.name)#AttributeError: 'Foo' object has no attribute 'name' f1 = Foo() print(f == f1)#False
__new__
class A: def __init__(self):#调用init前先执行new方法 print('in init function') def __new__(cls, *args, **kwargs): print('in new function') return object.__new__(A,*args,**kwargs)#new 方法必须有一个返回值 a = A() b = A() c = A() d = A()
object 将__new__()定义为静态方法,并且至少需要传递一个cls,cls表示需要实例化的类,此参数在实例化时由python解释器自动提供。
实例化对象的时候,在调用__init__()方法之前,先调用了__new__()方法
__new__()必须要有返回值,返回实例化出来的实例,需要注意的是,可以return父类__new__()出来的实例,也可以直接将object的__new__()出来的实例返回。
__init__()有一个参数self,该self参数就是__new__()返回的实例,__init__()在__new__()的基础上才可以完成其它初始化动作,__init__()不需要返回值。
若__new__()没有正确返回当前类的cls实例,那__init__()将不会被调用,即使是父类的实例也不行。
单例模式
单例模式是一种常用的设计模式,该模式的主要目的是确保某一个类只有一个实例存在。当你希望在整个系统中,某个类只能出现一个实例,单利对象就能派上用场。
class Singleton: def __new__(cls, *args, **kwargs): if not hasattr(cls,'a'): cls.a = object.__new__(cls,*args,**kwargs) return cls.a one = Singleton() two = Singleton() print(one,two) print(one == two)#True one 就是 two # <__main__.Singleton object at 0x0128FBD0> <__main__.Singleton object at 0x0128FBD0> one.name = "alex" print(two.name)
__call__
对象后面加括号,触发执行。
构造方法的执行是由创建对象触发的,即:对象 = 类名();而对于__call__方法的执行是由对象后加括号触发的,即:对象()或者类()
# class Foo: # def __init__(self): # pass # def __call__(self, *args, **kwargs): # print('__call__') # obj = Foo()#执行__init__ # obj()#__call__ class Storage(dict): # __call__方法用于实例自身的调用 #达到()调用的效果 def __call__ (self, key): try: return self[key] except KeyError as k: return None s = Storage() s['jjjk'] = 'aaaaa'#这里相当于添加了一个字典,调用key就会返回对应的value print (s('jjjk') )#调用__call__ 返回aaaaa
__len__
# class A: # def __init__(self): # self.a = 1 # self.b = 2 # self.c = 3 # def __len__(self): # return self.__dict__ # a = A() # print(a.__len__())#{'a': 1, 'b': 2, 'c': 3} class A: def __init__(self): self.a = 1 self.b = 2 self.c = 3 def __len__(self): return len(self.__dict__) a = A() print(len(a))# 3
__hash__
class A: def __init__(self): self.a = 1 self.b = 2 def __hash__(self): return hash(str(self.a)+str(self.b)) a = A() print(a.__hash__())#相当于print(hash(a))
__eq__
class A: def __init__(self): self.a = 1 self.b = 2 def __eq__(self, other): if self.a == other.a and self.b == other.b: return True#False(这里可以实现定制) a = A() b = A() print(a == b)