python------面向对象进阶
一、isinstance和issubclass
class A:pass class B(A):pass a = A() print(isinstance(a,A)) # True a是A的对象 print(issubclass(B,A)) # True B是A的派生类 print(issubclass(A,B)) # False # isinstance(obj,cls)检查是否obj是否是类 cls 的对象 # issubclass(sub, super)检查sub类是否是 super 类的派生类
二、反射
反射:根据字符串的形式去某个对象中操作它的成员
class Person: def __init__(self,name,sex,age): self.name = name self.sex = sex self.age = age def say(self): print('伊娃伊娃哟') p1 = Person('jim','男',20) print(hasattr(p1,'name')) #判断有木有,有则True,没有False print(getattr(p1,'sex')) #找不到报错 print(getattr(p1,'age1',22)) #可以设置返回值则不报错 del p1.name #删除属性方式一 print(p1.__dict__) delattr(p1,'name') #删除属性方式二 print(p1.__dict__) setattr(p1,'name','lucy') #设置属性值 print(p1.__dict__)
反射的好处:可以事先定义好接口,接口只有在被完成后才会真正执行,这实现了即插即用,它其实就是一种“后期绑定” 。
可以事先把主要的逻辑写好(只定义接口),然后后期再去实现接口的功能
class FtpClient: 'ftp客户端,但是还么有实现具体的功能' def __init__(self,addr): print('正在连接服务器[%s]'%addr) self.addr = addr
f1 = FtpClient('192.168.1.1') if hasattr(f1,'get'): func_get = getattr(f1,'get') func_get() else: print('---->不存在此方法') print('您可以先处理其它逻辑')
class A: def func(self): print('in func') a = A() a.name = 'alex' a.age = 63 # 反射对象的属性 ret = getattr(a,'name') # 通过变量名的字符串形式取到的值 # print(ret) # print(a.__dict__) # 变量名 = input('>>>') # func # print(getattr(a,变量名)) # print(a.__dict__[变量名]) # 反射对象的方法 a.func() ret = getattr(a,'func') ret()
class A: price = 20 @classmethod def func(cls): print('in func') # 反射类的属性 # A.price print(getattr(A,'price')) # 反射类的方法 :classmethod staticmethod # A.func() if hasattr(A,'func'): getattr(A,'func')()
#my.py文件 day = 'Monday' def wahaha(): print('wahahaha') class C: pass #导入my模块 import my # 反射模块的属性 print(my.day) # Monday print(getattr(my,'day')) # Monday # 反射模块的方法 getattr(my,'wahaha')() # wahahaha
import time print(getattr(time,'time')()) # 1516612064.430534 print(getattr(time,'asctime')()) # Mon Jan 22 17:07:44 2018
def qqxing(): print('qqxing') year = 2018 import sys # print(sys.modules['__main__'].year) # 反射自己模块中的变量 print(getattr(sys.modules['__main__'],'year')) # 2018 # 反射自己模块中的函数 getattr(sys.modules['__main__'],'qqxing')() # qqxing 变量名 = input('>>>') print(getattr(sys.modules[__name__],变量名)) # >>>
__setattr__ 添加/修改属性时会触发它的执行
__delattr__ 删除属性时会触发
__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.__dict__[key] = value def __delattr__(self, item): print('---->from delattr') self.__dict__.pop(item) # __setattr__添加/修改属性会触发它的执行 f1 = Foo(10) print(f1.__dict__) # {'y': 10} # 因为你重写了__setattr__,凡是赋值操作都会触发它的运行,你啥都没写,就是根本没赋值, # 除非你直接操作属性字典,否则永远无法赋值 f1.z = 3 print(f1.__dict__) # {'y': 10, 'z': 3} #__delattr__ 删除属性的时候会触发 f1.__dict__['a'] = 3 print(f1.__dict__) # {'z': 3, 'y': 10, 'a': 3} del f1.a print(f1.__dict__) # {'z': 3, 'y': 10} #__getattr__只有在使用点调用属性且属性不存在的时候才会触发 f1.xxxx #---->from getattr:你找的属性不存在
三、 __str__ 和 __repr__
改变对象的字符串显示__str__, __repr__
自定制格式字符串__format__
# 双下方法 # obj.__str__ str(obj) # obj.__repr__ repr(obj) class Teacher: def __init__(self,name,salary): self.name = name self.salary = salary def __str__(self): return "Teacher's object :%s"%self.name def __repr__(self): return str(self.__dict__) def func(self): return 'wahaha' nvshen = Teacher('女神',250) print(nvshen) # 打印一个对象的时候,就是调用a.__str__ print(repr(nvshen)) print('>>> %r'%nvshen) #a.__str__ --> object # object 里有一个__str__,一旦被调用,就返回调用这个方法的对象的内存地址 # %s str() 直接打印 实际上都是走的__str__ # %r repr() 实际上都是走的__repr__ # repr 是str的备胎,但str不能做repr的备胎 # print(obj)/'%s'%obj/str(obj)的时候,实际上是内部调用了obj.__str__方法,如果str方法有,那么他返回的必定是一个字符串 # 如果没有__str__方法,会先找本类中的__repr__方法,再没有再找父类中的__str__。 # repr(),只会找__repr__,如果没有找父类的
class B: def __str__(self): return 'str : class B' def __repr__(self): return 'repr : class B' b = B() print('%s' % b) # str : class B print('%r' % b) # repr : class B
四、 __del__
析构方法,当对象在内存中被释放时,自动触发执行
class A: def __del__(self): # 析构函数: 在删除一个对象之前进行一些收尾工作 print('执行我啦') self.f.close() a = A() a.f = open('my.py') # 打开文件 第一 在操作系统中打开了一个文件 拿到了文件操作符存在了内存中 del a # a.f 拿到了文件操作符消失在了内存中 # del a # del 既执行了这个方法,又删除了变量 # 引用计数
class Foo: def __del__(self): print('执行我啦') f1 = Foo() del f1 print('------->') #输出结果 ''' 执行我啦 -------> '''
五、 __call__
对象后面加括号,触发执行。
注:构造方法的执行是由创建对象触发的,即:对象 = 类名();而对于 __call__方法的执行是由对象后加括号触发的,
即:对象()或者类()()
class A: def __init__(self,name): self.name = name def __call__(self): ''' 打印这个对象中的所有属性 :return: ''' for k in self.__dict__: print(k,self.__dict__[k]) a = A('jim')()
六、item系列(__getitem__,__setitem__,__delitem__)
class Foo: def __init__(self,name,age,sex): self.name = name self.age = age self.sex = sex def __getitem__(self, item): if hasattr(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('egon',38,'男') print(f['name']) f['hobby'] = '男' print(f.hobby,f['hobby']) # del f.hobby # object 原生支持 __delattr__ del f['hobby'] # 通过自己实现的 print(f.__dict__)
七、__new__
构造方法 : 创建一个对象
class A: def __init__(self): self.x = 1 print('in init function') def __new__(cls, *args, **kwargs): print('in new function') return object.__new__(A, *args, **kwargs) a1 = A() #结果 # in new function # in init function a2 = A() #结果 # in new function # in init function a3 = A() #结果 # in new function # in init function print(a1) #<__main__.A object at 0x0000014CC7673B70> print(a2) #<__main__.A object at 0x0000014CC7673BA8> print(a3) #<__main__.A object at 0x0000014CC7673C18> print(a1.x) # 1
# 单例模式 # 一个类 始终 只有 一个 实例 # 当你第一次实例化这个类的时候 就创建一个实例化的对象 # 当你之后再来实例化的时候 就用之前创建的对象 class A: __instance = False def __init__(self,name,age): self.name = name self.age = age def __new__(cls, *args, **kwargs): if cls.__instance: return cls.__instance cls.__instance = object.__new__(cls) return cls.__instance jim = A('jim',38) jim.cloth = '小花袄' lucy = A('lucy',25) print(lucy) # <__main__.A object at 0x000002A579843BE0> print(jim) # <__main__.A object at 0x000002A579843BE0> print(lucy.name) # lucy print(jim.name) # lucy print(lucy.cloth) # 小花袄
八、__eq__
class A: def __init__(self,name): self.name = name def __eq__(self, other): if self.__dict__ == other.__dict__: return True else: return False ob1 = A('jim') ob2 = A('jim') ob3 = A('jim1') print(ob1 == ob2) # True print(ob1 == ob3) # False
九、__hash__
class A: def __init__(self,name,sex): self.name = name self.sex = sex def __hash__(self): return hash(self.name+self.sex) a = A('jim','男') b = A('jim','nv') print(hash(a)) # -4536380992615375499 print(hash(b)) # -4536380992615375499
十、__len__
class A: def __init__(self): self.a = 1 self.b = 2 def __len__(self): return len(self.__dict__) a = A() print(len(a)) # 2