目录
第四十四篇 面向对象高阶
一、isinstance()和issubclass()
1.isinstance()
判断对象是否为这个类实例化出来的,也会检测父类(比较数据类型推荐使用)
class Foo: pass class Bar(Foo): pass obj = Bar() # isinstance 可以检测到父类 print(isinstance(obj,Foo)) # True print(isinstance(obj,Bar)) # True print(isinstance(Bar,Foo)) # False # type 只检测到类 print(type(obj) == Bar) # True print(type(obj) == Foo) # False print(type(obj)) # <class '__main__.Bar'> print(type(Bar())) # <class '__main__.Bar'> print(type(Foo())) # <class '__main__.Foo'> # type 获取实例化对象的类,不会检测父类,可以用于生成类(type是元类)
2.issubclass()
比较判断某个类是否为另一个类的子类
class Foo: pass class Bar(Foo): pass print(issubclass(Bar, Foo))
二、反射
1.__import__()
通过字符串导入模块
time = __import__('time') print(time.time())
2.hasattr()
hasattr:通过字符串判断是否类属性存在
class Foo: def eat(self): print('rice') f = Foo() print(hasattr(f,'eat')) # True
3.getattr()
getattr:通过字符串获取类属性
class Foo: def eat(self): print('rice') f = Foo() print(getattr(f,'eat')) # 得到一个方法对象和地址 print(getattr(f,'eat')()) ''' rice None # 返回值为空 '''
4.setattr()
setattr:通过字符串修改类属性。如果有就修改,没有就添加
class Foo: def eat(self): print('rice') f = Foo() setattr(f,'eat','fruit') print(f.__dict__) # {'eat': 'fruit'} setattr(f,'play','game') # {'eat': 'fruit', 'play': 'game'}
5.delattr()
delattr:通过字符串删除类属性
class Foo: def eat(self): print('rice') f = Foo() print(f.__dict__) # {'eat':'rice'} delattr(f,'eat') print(f.__dict__) # {}
三、call() 和 new()
1.__call__()
**cls()()就会触发__call__()**
class Foo: def __init__(self): print('Foo()会触发,也就是实例化对象时触发') def __call__(self): print('Foo()()会触发,也即是对象调用方法时触发(其实主要用于元类中)') obj = Foo() # Foo()会触发... obj() # Foo()()会触发...
2.__new__()
1.用于实例化一个空对象时使用
**2.__new__(cls,*more),它的上面是一个非绑定方法装饰器@staticmethod**
class Foo: def __new__(self): # self:类本身 print('__new__') obj = object.__new__(self) # 实例化一个空对象。self:类本身 '''obj = self.__new__(self) 这样会出错,可以将self换成其他有__new__()方法的类,object作为基类就有__new__()方法''' return obj def __init__(self): # self 对象本身 print('__init__') f = Foo()
四、元类
1.元类用来造类的
**2.元类(),会触发__init__()生成类(元类实例化)**
**3.元类()(),会触发__call__()生成对象(类实例化)**
4.类分为几部分:class_name类名/class_dict类体名称空间/class_bases父类们
5.对象的属性查找顺序:对象---->类---->父类(如果有其他父类,也会广度优先查找其他父类)---->祖宗类---->object类---->自定义元类---->type
# 第一种方法造类:使用type模仿class关键字造类 # 步骤: # 1.类名class_name:比如 Foo # 2.类体代码class_body:开辟内存空间,把属性/方法放入一个名称空间(造好了才会有名称空间:如 Foo.__dict__),用class_dict来接 # 3.父类(基类)class_bases:(object,) # 4.exec() 方法:会把字符里的代码运行,并且放入名称空间 class_name = 'Foo' class_bases = (object,) class_body = ''' def __init__(self,name): self.name = name def speak(self): print('666') ''' class_dict = dict() exec(class_body,{},class_dict) # 将类体代码中的名字放入名称空间 cls_foo = type(class_name,class_bases,class_dict) # 元类实例化,生成类 obj = cls_foo('king') # 类实例化,生成对象 # 第二种方法造类:使用元类造类(可以控制造类的过程) class MyMeta(type): # 同样需要type元类来帮自定义的元类实例化一个类 def __init__(self,class_name,class_bases,class_dict): # 利用type元类来实例化一个类 # 可以在这个位置加上逻辑代码,控制类的产生 if not class_name.title(): raise TypeError('类名首字母必须大写') super().__init__(class_name,class_bases,class_dict) class Foo(object,metaclass=MyMeta): # metaclass=MyMeta是关键 def __init__(self): pass obj = Foo() # 实例化一个对象 # 控制对象的产生 class MyMeta(type): def __init__(self,class_name,class_bases,class_dict): # 这个位置控制类的产生 super().__init__(class_name,class_bases,class_dict) def __call__(self,*args,**kwargs): # 控制实例化对象时参数的传递 obj = self.__new__(self) self.__init__(obj,*args,**kwargs) # 控制对象的产生 return obj class Foo(object,metaclass=MyMeta): def __init__(self): pass obj = Foo()
五、单例模式
1.单例模式(Singleton Pattern):是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在。当你希望在整个系统中,某个类只能出现一个实例时,单例对象就能派上用场。
比如,某个服务器程序的配置信息存放在一个文件中,客户端通过一个 AppConfig 的类来读取配置文件的信息。如果在程序运行期间,有很多地方都需要使用配置文件的内容,也就是说,很多地方都需要创建 AppConfig 对象的实例,这就导致系统中存在多个 AppConfig 的实例对象,而这样会严重浪费内存资源,尤其是在配置文件内容很多的情况下。事实上,类似 AppConfig 这样的类,我们希望在程序运行期间只存在一个实例对象。
2.实现方法有许多种,我们来介绍下面这三种
- 1.利用类绑定方法
NAME = 'king' class Foo: __instance = None # 定义一个隐藏的类属性,用于接住实例化对象并返回 def __init__(self, name): self.name = name @classmethod # 类绑定方法 def func(cls): if cls.__instance: # 第一次不走这里 return cls.__instance # 第一次之后返回的都是相同的对象 obj = cls(NAME) # 这里写死了,只能接收NAME,所以只能实例化同一个对象 cls.__instance = obj # 类的__instance属性同样写死了,只能是这个对象了 return cls.__instance f = Foo.func() # <__main__.Foo object at 0x000002079E3FC7B8> f1 = Foo('jojo') # <__main__.Foo object at 0x000002079E3FC7B8>
- 2.利用装饰器
NAME = 'king' # 传入类的装饰器 def deco(cls): cls.__instance = cls(NAME) # 实例化一个固定的对象 def wrapper(*args,**kwargs): if len(args) == 0 and len(kwargs) == 0: return cls.__instance # 当不传参时,就是固定的对象 return cls(*args,**kwargs) # 传参之后就返回定制的对象 return wrapper @deco calss Foo: def __init__(self, name): self.name = name obj = Foo()
- 3.利用元类(重要)
NAME = 'king' # 元类 class MyMeta(type): def __init__(self,class_name,class_bases,class_dict): super().__init__(self,class_name,class_bases,class_dict) # 实例化一个类 self.__instance = self(NAME) # 实例化一个对象 def __call__(self,*args,**kwargs): if len(args) == 0 and len(kwargs) == 0: return self.__instance obj = self.__new__(self) # 实例化一个空对象 self.__init__(obj,*args,**kwargs) # 初始化对象 return obj class Foo(object,metaclass=MyMeta): # 会先去MyMeta中实例化一个类 def __init__(self,name): self.name = name obj = Foo() # 实例化一个对象
六、异常处理
# 1.捕捉异常 try: # 疑似有问题的代码,可以通过这个方法查看是否有报错 except: print('error') # 2.Exception 万能捕捉 try: # 疑似有问题的代码,可以通过这个方法查看是否有报错 except Exception as e: print(e) # 3.finally 无论是否报错,都会执行后面的代码,一般用于文件的关闭(不推荐) try: # 疑似有问题的代码,可以通过这个方法查看是否有报错 except Exception as e: print(e) finally: print('keep') # 4.raise() 主动抛出异常 try: # 代码块 raise NameError('not defind') except NameError as e: print(e) # 5.assert 断言,用于预估代码会出错,给个标记,方便报错时查找(不推荐) x = 0 y = x**2 assert y!=2
来源:https://www.cnblogs.com/itboy-newking/p/11072045.html