Python weakref.WeakKeyDictionary与weakref.WeakValueDictionary区别和实战应用

weakref模块主要的作用:就是一种弱类型的应用,使用此类型,内存管理不再以传统计数器的次数来实现内存的回收,
而是通过单独开辟的内存来存储实例的对象,然后通过指针地址引用的方式,实现对象的调用,
使用完成后,GC马上回收内存,从而达到高效回收内存,提高效率。

一、常用的方法有两种

weakref.WeakKeyDictionary : 实例化对象存在key里面,value可以自定义值
weakref.WeakValueDictionary : 实例化对象存在value里面,key可以自定义值

二、使用的示例

import weakref


class Config(object):

    def say(self):
        print('hello')


if __name__ == '__main__':
    ret_key = weakref.WeakKeyDictionary()
    ret_value = weakref.WeakValueDictionary()
    config_obj = Config()

    # 两者的区别
    ret_key[config_obj] = config_obj
    ret_value[config_obj] = config_obj
    print('WeakKeyDictionary:', ret_key.__dict__.get('data'))
    print('WeakValueDictionary:', ret_value.__dict__.get('data'))
    """
    打印结果:
       WeakKeyDictionary: {<weakref at 0x000001FD94E8C548; to 'Config' at 0x000001FD94756780>: <__main__.Config object at 0x000001FD94756780>}
       WeakValueDictionary: {<__main__.Config object at 0x000001FD94756780>: <weakref at 0x000001FD94E304C0; to 'Config' at 0x000001FD94756780>}
    """

    # 两者调用方法,都是一致的
    ret_key.get(config_obj).say()
    ret_value.get(config_obj).say()
    """
    打印结果:
        hello
        hello
    """

    # 自定义键或值
    ret_key[config_obj] = 'test'
    ret_value['test'] = config_obj

    print(ret_key.get(config_obj))
    print(ret_value.get('test'))
    """
    打印结果:
        test
        <__main__.Config object at 0x000001D224986828>
    """

三、实际应用

注意:此代码来源Tornado源码
httpclient.py

@classmethod
def _async_clients(cls) -> Dict[IOLoop, "AsyncHTTPClient"]:
    attr_name = "_async_client_dict_" + cls.__name__
    if not hasattr(cls, attr_name):
        setattr(cls, attr_name, weakref.WeakKeyDictionary()) #给实例化类属性增加一个WeakKeyDictionary的类型,然后把loop实例设置为key和value
    return getattr(cls, attr_name)

def __new__(cls, force_instance: bool = False, **kwargs: Any) -> "AsyncHTTPClient":
    io_loop = IOLoop.current()
    if force_instance:
        instance_cache = None
    else:
        instance_cache = cls._async_clients()
    if instance_cache is not None and io_loop in instance_cache:
        return instance_cache[io_loop]  # 在WeakKeyDictionary获取值
    instance = super(AsyncHTTPClient, cls).__new__(cls, **kwargs)  # type: ignore
    instance._instance_cache = instance_cache
    if instance_cache is not None:
        instance_cache[instance.io_loop] = instance # 给WeakKeyDictionary类型设置值
    return instance

四、小结:

上面的示例,其实就是实现对象的存储和调用,在实例项目中的使用,只有实战,才知道弱引用实际的应用

 

posted @ 2020-11-25 14:07  小粉优化大师  阅读(756)  评论(0编辑  收藏  举报