我正在尝试在python3中使用python2程序,它具有以下Meta类定义。在Py2上效果很好。使其与py2和py3都兼容的“最佳”方法是什么?
它在单元测试中失败了:
try:
raise Actor.DoesNotExist
except Actor.DoesNotExist:
pass
失败是:
AttributeError: type object 'Actor' has no attribute 'DoesNotExist'
基本元类定义为:
class MetaDocument(type):
def __new__(meta,name,bases,dct):
class DoesNotExist(BaseException):
pass
class MultipleDocumentsReturned(BaseException):
pass
dct['DoesNotExist'] = DoesNotExist
dct['MultipleDocumentsReturned'] = MultipleDocumentsReturned
class_type = type.__new__(meta, name, bases, dct)
if not class_type in document_classes:
if name == 'Document' and bases == (object,):
pass
else:
document_classes.append(class_type)
return class_type
class Document(object):
__metaclass__ = MetaDocument
您可以将MetaDocument()
元类用作工厂来产生替换您的Document
类的类,从而重新使用类属性:
class Document(object):
# various and sundry methods and attributes
body = vars(Document).copy()
body.pop('__dict__', None)
body.pop('__weakref__', None)
Document = MetaDocument(Document.__name__, Document.__bases__, body)
这不需要您手动构建第三个参数,即类主体。
您可以将其变成类装饰器:
def with_metaclass(mcls):
def decorator(cls):
body = vars(cls).copy()
# clean out class body
body.pop('__dict__', None)
body.pop('__weakref__', None)
return mcls(cls.__name__, cls.__bases__, body)
return decorator
然后用作:
@with_metaclass(MetaDocument)
class Document(object):
# various and sundry methods and attributes
或者,为此使用six
库:
@six.add_metaclass(MetaDocument)
class Document(object):
其中,@six.add_metaclass()
装饰也需要的任何照顾__slots__
你可能已经定义; 我上面的简单版本没有。
six
还有一个six.with_metaclass()
基层工厂:
class Document(six.with_metaclass(MetaDocument)):
这为MRO注入了额外的基类。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句