如何创建在 Python2 和 Python3 上运行的元类实例?
元类是生成其他类的类。它是一个有效的类验证工具,可以防止子类继承某些类的函数,动态生成类。在这里,我们将讨论如何创建一个可以在Python 2 和Python 3 上运行的元类的实例。在深入研究之前,让我们先了解一下每个Python版本的代码设计。
Python3
在Python 3 中,通过将元类提供给元类关键字参数,在声明类时创建元类的实例。让我们看看在Python 3 中执行此操作的首选方法。
Python3
class MetaCls(type):
def __new__(cls, name, bases, attrs):
return super(MetaCls, cls).__new__(cls, name, bases, attrs)
class C(object, metaclass=MetaCls):
pass
print('Type of class C:',type(C))
Python
class MetaCls(type):
def __new__(cls, name, bases, attrs):
return super(MetaCls, cls).__new__(cls, name, bases, attrs)
class C(object):
__metaclass__ = MetaCls
print(type(C))
Python3
import six
class MetaCls(type):
def __new__(cls, name, bases, attrs):
return super(MetaCls, cls).__new__(cls, name, bases, attrs)
class C(six.with_metaclass(MetaCls)):
pass
print(type(C))
Python3
import six
class MetaCls(type):
def __new__(cls, name, bases, attrs):
return super(MetaCls, cls).__new__(cls, name, bases, attrs)
@six.add_metaclass(MetaCls)
class C(object):
pass
print(type(C))
Type of class C:
在这里,我们通过为metaclass关键字参数提供MetaCls类,创建了一个名为C的类。您可以将C类的类型视为MetaCls。
注意:MetaCls 是一个直接继承自 type 的元类。
Python2
现在,让我们看看如何在Python 2 中创建元类的实例。在Python 3 中,我们已经看到在类声明的关键字参数中提到了元类;而在Python 2 中,元类是通过使用 __metaclass__ 属性在类体中分配的。让我们看看下面的代码:
Python
class MetaCls(type):
def __new__(cls, name, bases, attrs):
return super(MetaCls, cls).__new__(cls, name, bases, attrs)
class C(object):
__metaclass__ = MetaCls
print(type(C))
在Python 2 和Python 3 上运行的元类代码
现在很清楚Python 2 和Python 3 中的语法有何不同。如果您尝试将Python 2 代码迁移到Python 3,这种语法差异可能会造成麻烦。由于Python 3 向后不兼容,因此Python 3 语法不会执行在Python 2 上,反之亦然。
一个名为6的工具的重要性由此而来。它提供了两种方法来声明元类以确保交叉兼容性。
- 通过创建一个替身类
- 作为装饰者
在第一种方法中,我们将创建一个替代类并将其用作直接子类。让我们看看下面的代码。
蟒蛇3
import six
class MetaCls(type):
def __new__(cls, name, bases, attrs):
return super(MetaCls, cls).__new__(cls, name, bases, attrs)
class C(six.with_metaclass(MetaCls)):
pass
print(type(C))
现在,让我们看看如何使用装饰器创建元类的实例。
蟒蛇3
import six
class MetaCls(type):
def __new__(cls, name, bases, attrs):
return super(MetaCls, cls).__new__(cls, name, bases, attrs)
@six.add_metaclass(MetaCls)
class C(object):
pass
print(type(C))