Saturday 14 October 2017
oop - What are metaclasses in Python?
Answer
Answer
What are metaclasses and what do
we use them for?
A
metaclass is the class of a class. A class defines how an instance of the class (i.e. an
object) behaves while a metaclass defines how a class behaves. A class is an instance of
a metaclass.
While in Python you can use
arbitrary callables for metaclasses (like href="https://stackoverflow.com/questions/100003/what-is-a-metaclass-in-python/100037#100037">Jerub
shows), the better approach is to make it an actual class itself.
type
is the usual metaclass in Python.
type
is itself a class, and it is its own type. You won't be
able to recreate something like type
purely in Python, but
Python cheats a little. To create your own metaclass in Python you really just want to
subclass type
.
A
metaclass is most commonly used as a class-factory. When you create an object by calling
the class, Python creates a new class (when it executes the 'class' statement) by
calling the metaclass. Combined with the normal __init__
and
__new__
methods, metaclasses therefore allow you to do 'extra
things' when creating a class, like registering the new class with some registry or
replace the class with something else
entirely.
When the
class
statement is executed, Python first executes the body of
the class
statement as a normal block of code. The resulting
namespace (a dict) holds the attributes of the class-to-be. The metaclass is determined
by looking at the baseclasses of the class-to-be (metaclasses are inherited), at the
__metaclass__
attribute of the class-to-be (if any) or the
__metaclass__
global variable. The metaclass is then called
with the name, bases and attributes of the class to instantiate
it.
However, metaclasses actually define the
type of a class, not just a factory for it, so you can do much more
with them. You can, for instance, define normal methods on the metaclass. These
metaclass-methods are like classmethods in that they can be called on the class without
an instance, but they are also not like classmethods in that they cannot be called on an
instance of the class. type.__subclasses__()
is an example of a
method on the type
metaclass. You can also define the normal
'magic' methods, like __add__
,
__iter__
and __getattr__
, to implement
or change how the class behaves.
Here's an
aggregated example of the bits and
pieces:
def
make_hook(f):
"""Decorator to turn 'foo' method into '__foo__'"""
f.is_hook = 1
return f
class
MyType(type):
def __new__(mcls, name, bases, attrs):
if
name.startswith('None'):
return None
# Go over
attributes and see if they should be renamed.
newattrs =
{}
for attrname, attrvalue in attrs.iteritems():
if
getattr(attrvalue, 'is_hook', 0):
newattrs['__%s__' % attrname] =
attrvalue
else:
newattrs[attrname] =
attrvalue
return super(MyType, mcls).__new__(mcls, name, bases,
newattrs)
def __init__(self, name, bases, attrs):
super(MyType, self).__init__(name, bases, attrs)
#
classregistry.register(self, self.interfaces)
print "Would register class %s
now." % self
def __add__(self, other):
class
AutoClass(self, other):
pass
return AutoClass
#
Alternatively, to autogenerate the classname as well as the class:
# return
type(self.__name__ + other.__name__, (self, other), {})
def unregister(self):
# classregistry.unregister(self)
print
"Would unregister class %s now." % self
class MyObject:
__metaclass__ = MyType
class
NoneSample(MyObject):
pass
# Will print
"NoneType None"
print type(NoneSample),
repr(NoneSample)
class Example(MyObject):
def
__init__(self, value):
self.value = value
@make_hook
def add(self, other):
return self.__class__(self.value +
other.value)
# Will unregister the
class
Example.unregister()
inst = Example(10)
#
Will fail with an AttributeError
#inst.unregister()
print
inst + inst
class Sibling(MyObject):
pass
ExampleSibling = Example + Sibling
# ExampleSibling
is now a subclass of both Example and Sibling (with no
# content of its own)
although it will believe it's called 'AutoClass'
print
ExampleSibling
print
ExampleSibling.__mro__
php - file_get_contents shows unexpected output while reading a file
I want to output an inline jpg image as a base64 encoded string, however when I do this : $contents = file_get_contents($filename); print &q...
-
I have an app which needs a login and a registration with SQLite. I have the database and a user can login and register. But i would like th...
-
I got an error in my Java program. I think this happens because of the constructor is not intialized properly. My Base class Program public ...
-
I would like to use enhanced REP MOVSB (ERMSB) to get a high bandwidth for a custom memcpy . ERMSB was introduced with the Ivy Bridge micro...
No comments:
Post a Comment