所以,我有一个元类来缓存它所创建的对象的实例,以避免重复实例:
class _CachingMeta(type):
__cache__ = {}
def __init__(self, n, b, d):
# ... Do stuff...
return super(_CachingMeta, self).__init__(n, b, d)
def __call__(cls, *a, **kw):
# Simplified caching key
key = frozenset((cls, frozenset(a), frozenset(kw.items())))
if key not in _CachingMeta.__cache__:
_CachingMeta.__cache__[key] = super(_CachingMeta, cls).__call__(*a, **kw)
return _CachingMeta.__cache__[key]
class StaticClass(object):
__metaclass__ = _CachingMeta
def __init__(self, *a, **kw):
pass
inst1 = StaticClass('arg1')
inst2 = StaticClass('arg1')
inst3 = StaticClass('arg3')
print (inst1)
print (inst2)
print (inst3)
打印:
<__main__.StaticClass object at 0x7f7ad8690c90>
<__main__.StaticClass object at 0x7f7ad8690c90>
<__main__.StaticClass object at 0x7f7ad8690d10>
我还想动态创建类,我希望缓存这些类的类和实例,我想我可以创建一个扩展_CachingMeta
并将其用作{{__metaclass__
的元类。 1}},但这似乎失败了,我无法理解为什么,例如:
class _ClassCachingMeta(_CachingMeta):
'''
Purpose: to cache generated classes and their instances
'''
__metaclass__ = _CachingMeta
def create_class(param):
class DynamicClass(object):
__metaclass__ = _ClassCachingMeta # A meta class that caches both the classes it creates and their instances
__param__ = param
return DynamicClass
打印:
Traceback (most recent call last):
File "../test2.py", line 29, in <module>
class _ClassCachingMeta(_CachingMeta):
File "../test2.py", line 7, in __init__
return super(_CachingMeta, self).__init__(n, b, d)
TypeError: Error when calling the metaclass bases
descriptor '__init__' requires a 'type' object but received a 'str'
似乎_ClassCachingMeta
在调用它__init__
之前没有得到绑定的__metaclass__.__init__
方法(我猜这是相同的方法/函数?)(例如):< / p>
class _CachingMeta(type):
__cache__ = {}
def __init__(self, n, b, d):
print ("initilizing {0}".format(self))
print (super(_CachingMeta, self).__init__)
return super(_CachingMeta, self).__init__(n, b, d)
def __call__(cls, *a, **kw):
# Simplified caching key
key = frozenset((cls, frozenset(a), frozenset(kw.items())))
if key not in _CachingMeta.__cache__:
_CachingMeta.__cache__[key] = super(_CachingMeta, cls).__call__(*a, **kw)
return _CachingMeta.__cache__[key]
class StaticClass(object):
__metaclass__ = _CachingMeta
def __init__(self, *a, **kw):
pass
class _ClassCachingMeta(_CachingMeta):
'''
Purpose: to cache generated classes and their instances
'''
__metaclass__ = _CachingMeta
def create_class(param):
class DynamicClass(object):
__metaclass__ = _ClassCachingMeta # Cache the class and it's instances
__param__ = param
return DynamicClass
给出:
initilizing <class '__main__.StaticClass'>
<method-wrapper '__init__' of _CachingMeta object at 0xc44cf0>
initilizing <class '__main__._ClassCachingMeta'>
<slot wrapper '__init__' of 'type' objects>
Traceback (most recent call last):
File "../test2.py", line 32, in <module>
class _ClassCachingMeta(_CachingMeta):
File "../test2.py", line 9, in __init__
return super(_CachingMeta, self).__init__(n, b, d)
TypeError: Error when calling the metaclass bases
descriptor '__init__' requires a 'type' object but received a 'str'
有没有直接的方法来实现这一点,还是我需要采用不同的方法?此外,如果有人可以帮助我理解为什么一个类不能扩展它自己的__metaclass__
那将是非常棒的。
答案 0 :(得分:2)
如果您尝试使用元类作为其自己的子类的元类,则子类既是第一个类的实例,也是子类。
super(thing, other)
可能意味着两件事之一,具体取决于other
是thing
的实例还是子类。当other
一个实例和一个子类时,super
会变得非常困惑。
解决super
的歧义并不是一个好方法。最好避免这种情况。