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

链接

#(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
')
原文地址:https://www.cnblogs.com/zh-xiaoyuan/p/13236216.html