I want to ask what the with_metaclass()
call means in the definition of a class.
E.g.:
class Foo(with_metaclass(Cls1, Cls2)):
- Is it a special case where a class inherits from a metaclass?
- Is the new class a metaclass, too?
I want to ask what the with_metaclass()
call means in the definition of a class.
E.g.:
class Foo(with_metaclass(Cls1, Cls2)):
with_metaclass()
is a utility class factory function provided by the six
library to make it easier to develop code for both Python 2 and 3.
It creates a base class with the specified meta class for you, compatible with the version of Python you are running the code on.
Quoting from the documentation:
Create a new class with base class base and metaclass metaclass. This is designed to be used in class declarations like this:
from six import with_metaclass class Meta(type): pass class Base(object): pass class MyClass(with_metaclass(Meta, Base)): pass
This is needed because the syntax to attach a metaclass changed between Python 2 and 3:
Python 2:
class MyClass(object):
__metaclass__ = Meta
Python 3:
class MyClass(metaclass=Meta):
pass
The with_metaclass()
function makes use of the fact that metaclasses are a) inherited by subclasses, and b) a metaclass can be used to generate new classes; it effectively creates a new base class by using the metaclass as a factory to generate an empty class:
def with_metaclass(meta, *bases):
"""Create a base class with a metaclass."""
return meta("NewBase", bases, {})
The NewBase
base class's metaclass is meta
, both on Python 2 and 3.
UPDATE: the six.with_metaclass()
function has since been patched with a decorator variant, i.e. @six.add_metaclass()
. This update fixes some mro issues related to the base objects. The new decorator would be applied as follows:
import six
@six.add_metaclass(Meta)
class MyClass(Base):
pass
Here are the patch notes and here is a similar, detailed example and explanation for using a decorator alternative.