zoukankan      html  css  js  c++  java
  • 第四十四篇 面向对象高阶

    第四十四篇 面向对象高阶

    一、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
    
  • 相关阅读:
    C#使用SSDB管理增量日志并提供查询
    请假系统特例规则详细设计
    2014年国内最热门的.NET开源平台
    MQTT--入门
    转MQTT--Python进行发布、订阅测试
    Python修改文件权限
    Python Windows文件操作
    python random 学习
    Python---copy()、deepcopy()与赋值的区别
    使用Git Bash从Git上下载代码到本地以及上传代码到码云Git
  • 原文地址:https://www.cnblogs.com/itboy-newking/p/11072045.html
Copyright © 2011-2022 走看看