• 面向对象中有哪些双下线方法及应用场景


    链接

    #(1)__init__:初始化
    #(2)__str__:在打印时改变对象的字符串显示,在打印类的时候会调用此方法,返回的是一个字符串
    #(3)__repr__
    
    #(4)__new__:创建对象。执行__init__之前执行__new__方法,在单例/rest framework序列化中使用过
            #在rest framework序列化源码中的使用
            class BaseSerializer(Field):
                def __init__(self, instance=None, data=empty, **kwargs):
                    self.instance = instance
                    if data is not empty:
                        self.initial_data = data
                    self.partial = kwargs.pop('partial', False)
                    self._context = kwargs.pop('context', {})
                    kwargs.pop('many', None)
                    super().__init__(**kwargs)
    
                def __new__(cls, *args, **kwargs):
                    # We override this method in order to automagically create
                    # `ListSerializer` classes instead when `many=True` is set.
                    if kwargs.pop('many', False):
                        return cls.many_init(*args, **kwargs)
                    return super().__new__(cls, *args, **kwargs)
                    
    #(5)__call__:对象()触发。flask源码请求入口,django请求入口(WSGIHandler.__call__)。
            #在flask源码请求入口中的使用
            class Flask(_PackageBoundObject):
                def __call__(self, environ, start_response):
                return self.wsgi_app(environ, start_response)
                
            #在django源码请求入口中的使用  
            class WSGIHandler(base.BaseHandler):
                request_class = WSGIRequest
    
                def __init__(self, *args, **kwargs):
                    super().__init__(*args, **kwargs)
                    self.load_middleware()
    
                def __call__(self, environ, start_response):
                    set_script_prefix(get_script_name(environ))
                    signals.request_started.send(sender=self.__class__, environ=environ)
                    request = self.request_class(environ)
                    response = self.get_response(request)
                    #……
    
    #(6)__getattr__ :对象.属性 触发
    #(7)__setattr__:对象.属性 = xxx 触发
    #(8)__delattr__:在flask源码Local对象中使用了这三个,见最下方
    
    #(9)__setitem__
    #(10)__getitem__
    #(11)__delitem__ :对象['xx']会触发这个三个
        class Foo(object):
    
            def __getitem__(self, item):
                return 1
    
            def __setitem__(self, key, value):
                pass
                
            def __delitem__(self, key):
                pass
                
        obj = Foo()
        obj['k1']           #触发__getitem__
        obj['k1'] = 123     #触发__setitem__
        del obj['k1']       #触发__delitem__
    
    #(12)__dict__,api封装返回数据时:BaseResponse
    #(13)__mro__, 继承顺序
    #(14)__slots__,Local对象
    #(15)__iter__,一个类中如果含此方法并返回一个迭代器,那么这个对象就是一个可迭代对象
    #flask源码Local对象 class Local(object): __slots__ = ('__storage__', '__ident_func__') #__slots__中设置的值就是外部能访问的值 def __init__(self): # __storage__ = {1231:{'stack':[]}} object.__setattr__(self, '__storage__', {}) object.__setattr__(self, '__ident_func__', get_ident) def __getattr__(self, name): try: return self.__storage__[self.__ident_func__()][name] except KeyError: raise AttributeError(name) def __setattr__(self, name, value): ident = self.__ident_func__() #相当于ident = get_ident() storage = self.__storage__ #相当于storge = {} try: storage[ident][name] = value except KeyError: storage[ident] = {name: value} #唯一标识不存在情况下就进行设置 def __delattr__(self, name): try: del self.__storage__[self.__ident_func__()][name] except KeyError: raise AttributeError(name)

     上下文管理协议 (with 方法)

        __enter____exit__
      用途或者说好处:

      1.使用with语句的目的就是把代码块放入with中执行,with结束后,自动完成清理工作,无须手动干预

      2.在需要管理一些资源比如文件,网络连接和锁的编程环境中,可以在__exit__中定制自动释放资源的机制,你无须再去关系这个问题,这将大有用处

    # __enter__和__exit__
    
    class Foo:
        def __enter__(self):  #with 拿到一个对象,触发enter方法
            print('enter')
            return 11111
        def __exit__(self, exc_type, exc_val, exc_tb): #文件打开执行完毕后,执行exit方法
            print('exit')
            print('exc_type',exc_type)  #异常的类型
            print('exc_val',exc_val)    #异常的值
            print('exc_tb',exc_tb)      #异常的内存地址
            return True #清空所有异常,抛异常之后,with后的内容正常执行。
    with Foo() as obj:  #执行Foo().__enter__方法得到一个返回值,然后将这个值赋给obj。
        #出现with语句, 对象的__enter__被触发, 有返回值则赋值给as声明的变量
        print('with Foo 的子代码块',obj) #执行with模块字代码
        raise NameError('名字没有定义!')  #只要是报异常,没有处理的话,就意味着with执行的字代码块运行完。触发exit方法,这之后的代码就不会再执行。
        print('##############')
    print('**************')
    
    #执行结果:
    enter
    with Foo 的子代码块 11111
    exit
    exc_type <class 'NameError'>
    exc_val 名字没有定义!
    exc_tb <traceback object at 0x00000000028EE948>
    **************

    例子:实现上下文的管理协议:(with方法打开文件执行操作!)

    class Open:
        def __init__(self,filepath,mode,encode='utf-8'):
            self.f=open(filepath,mode=mode,encoding=encode)
            self.filepath=filepath
            self.mode=mode
            self.encoding=encode
    
        def write(self,line):
            print('write')
            self.f.write(line)
    
        def __getattr__(self, item):
            return getattr(self.f,item)
    
        def __enter__(self): #with 对象 就会触发对象下的该方法
            return self  #将对象返回 write_file=Open('aaaaa.txt','w')
            #return self.f #这就是返回真实的open方法,字代码块的方法都可以使用,但是就不再是类Open的使用。
        def __exit__(self, exc_type, exc_val, exc_tb):#文件结束清理
            self.f.close()
            return True
    
    with Open('aaaaa.txt','w') as write_file: #变相的实例化 write_file=Open('aaaaa.txt','w')拿到产生的文件句柄
        write_file.write('123123123123123
    ')
        write_file.write('123123123123123
    ')
        write_file.write('123123123123123
    ')
  • 相关阅读:
    第七章 下
    第七章 上
    第六章 下
    第六章 上
    第五章 下
    linux 系统通过安装包安装mysql 8 步骤(非MariaDB)
    热烈庆祝博客换了新皮肤
    异常处理
    栈计算逆波兰表达式
    栈计算中缀表达式
  • 原文地址:https://www.cnblogs.com/zh-xiaoyuan/p/13236216.html
Copyright © 2020-2023  润新知