I have a class object, cls
. I want to know its metaclass. How do I do this?
(If I wanted to know its parent classes, I would do cls.__mro__
. Is there something like this to get the metaclass?)
In order to set metaclass of a class, we use the __metaclass__ attribute. Metaclasses are used at the time the class is defined, so setting it explicitly after the class definition has no effect.
In object-oriented programming, a metaclass is a class whose instances are classes. Just as an ordinary class defines the behavior of certain objects, a metaclass defines the behavior of certain classes and their instances. Not all object-oriented programming languages support metaclasses.
In UML, a metaclass is an instance of the Class element with the. stereotype Standard::Metaclass. The code you describe determines if a. class is a metaclass instead by checking whether the Metaclass. stereotype is applied.
You can define your own metaclasses that is a type of type that allows to define types. To make it clearer, a class describes what an object looks like, and is used at runtime to instantiate objects. A metaclass describes what a class looks like, and is used at compile time to instantiate classes.
Ok - so, a class's metaclass is just its own "type", and can be given by
type(cls)
and other means such as cls.__class__
.
In Python 3.x there are no further ambiguities - as the syntax for creating a metaclass just passes it as a named parameter on the class declaration statement anyway.
However, the syntax used for creating a metaclass in Python 2.x generates a side-effect that is worth noting.
Upon doing
class A(object):
__metaclass__ = MyMeta
The __metaclass__
attribute is set to that value in the actual class, even if the actual metaclass is another one.
Consider:
def class_pre_decorator(name, bases, namespace):
# do something with namespace
return type(name, bases, namespace)
This is a callable that can be used in the metaclass declaration of both Python 2 and 3 - and it is valid. After resolving, the actual metaclass in both cases will simply be type
. However, in Python 2.x, cls.__metaclass__
will point to the callable class_pre_decorator
, even tough type(cls)
returns type
, which is the correct metaclass.(Note that using callables in this way, they will not be used agian when the class is further subclassed)
There is no way in Python 3 to guess the callable actually used to instantiate a class if it gives no other hint (like setting an attribute on the class) that it was used:
# python 2
class A(object):
__metaclass__ = class_pre_decorator
On the console:
In [8]: type(A)
Out[8]: type
In [9]: A.__metaclass__
Out[9]: <unbound method A.class_pre_decorator>
and
# Python 3
class A(metaclass=class_pre_decorator):
pass
And trying to read A.__metaclass__
will simply raise an AttributeError.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With