5

使用Python元编程创建缓存实例

 2 years ago
source link: https://allenwind.github.io/blog/4970/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
Mr.Feng Blog

NLP、深度学习、机器学习、Python、Go

使用Python元编程创建缓存实例

元编程创建缓存实例

单例模式要求一个类只能创建一个实例,缓存类和单例模式类似,前者要求一个标识符(名字)关联到一个唯一的类实例。例如Python模块logging中的getLogger函数的行为:一个名字关联到一个日志类实例,如果我们尝试用同一个名字创建多个实例,发现这些实例都是唯一的(一样的),这种行为和单例模式很像,因此,我们可以把缓存类称为名字单例模式。

下面我们来看看logging中的行为:

>>> import logging
>>> a = logging.getLogger('a')
>>> b = logging.getLogger('a')
>>> a is b
True
>>> c = logging.getLogger('c')
>>> a is c
False
>>>

实现依据名字缓存实例的效果,首先想到的数据结构就是字典。通过字典绑定名字和实例即可。每次创建或访问通过该字典缓存实例,而字典的键是唯一的,因此可以实现“名字单例模式”。但普通的字典在缓存类实例时会为该对象添加一个引用计数,这样,当外界不再使用该实例时,对象的引用计数依然不为0,导致它无法被垃圾回收。因此这里使用弱引用字典。即:

import weakref

_cache = weakref.WeakValueDictionary()

def getLogger(name):
c = _cache.get(name, None)
if c is None:
c = Logger(name)
_cache[name] = c
return c
else:
return c

除了使用工厂方法外,还可以使用类的方式,后者更优雅。

import weakref

class Logger:

_cache = weakref.WeakValueDictionary()

def __init__(self, name):
self.name = name

def __new__(cls, name):
if name in cls._cache:
return cls._cache[name]
else:
self = super().__new__(cls)
cls._cache[name] = self
return self

# other logger method

如果要实现更负责的缓存类实例管理,可以把WeakValueDictionary从缓存类Logger分离开来,实现单独管理缓存实例的类,达到创建实例和缓存实例的松耦合。

最后,还有一种更高级的思路,使用元编程。元类负责管理类的创建,而具体类负责功能的实现。

import weakref

class Cached(type):

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.__cache = weakref.WeakValueDictionary()

# 创建具体实例
def __call__(self, name):
if name in self.__cache:
return self.__cache[name]
else:
self = super().__call__(name)
self.__cache[name] = self
return self

class Logger(metaclass=Cached):

def __init__(self, name):
self.name = name

# other logger method

可见,元类也是创建实例和缓存实例结构的方式,而且使用元类代码更简洁。

转载请包括本文地址:https://allenwind.github.io/blog/4970
更多文章请参考:https://allenwind.github.io/blog/archives/


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK