- 1. 假设你不想任何人创建这个类的实例
- 链接]">2. 假如你想实现单例模式 [链接]
- 3. 元类实现缓存实例
你想通过改变实例创建方式来实现单例、缓存或其他类似的特性。
如果你想自定义这个步骤,你可以定义一个元类并自己实现 call() 方法。
1. 假设你不想任何人创建这个类的实例
class NoInstances(type):
def __call__(self, *args, **kwargs):
raise TypeError("Can't instantuate directly")
class Spam(metaclass=NoInstances):
@staticmethod
def grok(x):
print('Spam.grok')
Spam.grok(42)
# Spam.grok
s = Spam()
# TypeError: Can't instantuate directly
2. 假如你想实现单例模式 [链接]
class Singleton(type):
def __init__(self, *args, **kwargs):
self.__instance = None
super().__init__(*args, **kwargs)
def __call__(self, *args, **kwargs):
if self.__instance is None:
self.__instance = super().__call__(*args, **kwargs)
return self.__instance
else:
return self.__instance
class Spam(metaclass=Singleton):
def __init__(self):
print('Creating Spam')
a = Spam()
b = Spam()
print(a is b)
# True
c = Spam()
print(a is c)
# True
3. 元类实现缓存实例
import weakref
class Cached(type):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.__cache = weakref.WeakValueDictionary()
def __call__(self, *args):
if args in self.__cache:
return self.__cache[args]
else:
obj = super().__call__(*args)
self.__cache[args] = obj
return obj
class Spam(metaclass=Cached):
def __init__(self, name):
print('Creating Spam({!r})'.format(name))
self.name = name
a = Spam('Guido')
# Creating Spam('Guido')
b = Spam('Diana')
# Creating Spam('Diana')
c = Spam('Guido')
# Cached
print(a is b)
# False
print(a is c)
# True