(window.webpackJsonp=window.webpackJsonp||[]).push([[2745],{3154:function(s,t,a){"use strict";a.r(t);var n=a(31),e=Object(n.a)({},(function(){var s=this,t=s.$createElement,a=s._self._c||t;return a("ContentSlotsDistributor",{attrs:{"slot-key":s.$parent.slotKey}},[a("h1",{attrs:{id:"metaclasses"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#metaclasses"}},[s._v("#")]),s._v(" Metaclasses")]),s._v(" "),a("p",[s._v("Metaclasses allow you to deeply modify the behaviour of Python classes (in terms of how they're defined, instantiated, accessed, and more) by replacing the "),a("code",[s._v("type")]),s._v(" metaclass that new classes use by default.")]),s._v(" "),a("h2",{attrs:{id:"basic-metaclasses"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#basic-metaclasses"}},[s._v("#")]),s._v(" Basic Metaclasses")]),s._v(" "),a("p",[s._v("When "),a("code",[s._v("type")]),s._v(" is called with three arguments it behaves as the (meta)class it is, and creates a new instance, ie. it produces a new class/type.")]),s._v(" "),a("div",{staticClass:"language-py extra-class"},[a("pre",{pre:!0,attrs:{class:"language-py"}},[a("code",[s._v("Dummy "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[s._v("type")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[s._v("'OtherDummy'")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[s._v("dict")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),s._v("x"),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),a("span",{pre:!0,attrs:{class:"token number"}},[s._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\nDummy"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),s._v("__class__ "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("# ")]),s._v("\nDummy"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),s._v("__class__"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),s._v("__class__ "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("# ")]),s._v("\n\n")])])]),a("p",[s._v("It is possible to subclass "),a("code",[s._v("type")]),s._v(" to create an custom metaclass.")]),s._v(" "),a("div",{staticClass:"language-py extra-class"},[a("pre",{pre:!0,attrs:{class:"language-py"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("class")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("mytype")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[s._v("type")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(":")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("def")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("__init__")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),s._v("cls"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v(" name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v(" bases"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[s._v("dict")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(":")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("# call the base initializer")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token builtin"}},[s._v("type")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),s._v("__init__"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),s._v("cls"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v(" name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v(" bases"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[s._v("dict")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("# perform custom initialization...")]),s._v("\n cls"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),s._v("__custom_attribute__ "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[s._v("2")]),s._v("\n\n")])])]),a("p",[s._v("Now, we have a new custom "),a("code",[s._v("mytype")]),s._v(" metaclass which can be used to create classes in the same manner as "),a("code",[s._v("type")]),s._v(".")]),s._v(" "),a("div",{staticClass:"language-py extra-class"},[a("pre",{pre:!0,attrs:{class:"language-py"}},[a("code",[s._v("MyDummy "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" mytype"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[s._v("'MyDummy'")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[s._v("dict")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),s._v("x"),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),a("span",{pre:!0,attrs:{class:"token number"}},[s._v("2")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\nMyDummy"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),s._v("__class__ "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("# ")]),s._v("\nMyDummy"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),s._v("__class__"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),s._v("__class__ "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("# ")]),s._v("\nMyDummy"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),s._v("__custom_attribute__ "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("# 2")]),s._v("\n\n")])])]),a("p",[s._v("When we create a new class using the "),a("code",[s._v("class")]),s._v(" keyword the metaclass is by default chosen based on upon the baseclasses.")]),s._v(" "),a("div",{staticClass:"language-py extra-class"},[a("pre",{pre:!0,attrs:{class:"language-py"}},[a("code",[a("span",{pre:!0,attrs:{class:"token operator"}},[s._v(">>")]),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v(">")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("class")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("Foo")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[s._v("object")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(":")]),s._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("pass")]),s._v("\n\n"),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v(">>")]),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v(">")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[s._v("type")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),s._v("Foo"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n"),a("span",{pre:!0,attrs:{class:"token builtin"}},[s._v("type")]),s._v("\n\n")])])]),a("p",[s._v("In the above example the only baseclass is "),a("code",[s._v("object")]),s._v(" so our metaclass will be the type of "),a("code",[s._v("object")]),s._v(", which is "),a("code",[s._v("type")]),s._v(". It is possible override the default, however it depends on whether we use Python 2 or Python 3:")]),s._v(" "),a("p",[s._v("A special class-level attribute "),a("code",[s._v("__metaclass__")]),s._v(" can be used to specify the metaclass.")]),s._v(" "),a("div",{staticClass:"language-py extra-class"},[a("pre",{pre:!0,attrs:{class:"language-py"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("class")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("MyDummy")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[s._v("object")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(":")]),s._v("\n __metaclass__ "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" mytype\n"),a("span",{pre:!0,attrs:{class:"token builtin"}},[s._v("type")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),s._v("MyDummy"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("# ")]),s._v("\n\n")])])]),a("p",[s._v("A special "),a("code",[s._v("metaclass")]),s._v(" keyword argument specify the metaclass.")]),s._v(" "),a("div",{staticClass:"language-py extra-class"},[a("pre",{pre:!0,attrs:{class:"language-py"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("class")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("MyDummy")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),s._v("metaclass"),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v("mytype"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(":")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("pass")]),s._v("\n"),a("span",{pre:!0,attrs:{class:"token builtin"}},[s._v("type")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),s._v("MyDummy"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("# ")]),s._v("\n\n")])])]),a("p",[s._v("Any keyword arguments (except "),a("code",[s._v("metaclass")]),s._v(") in the class declaration will be passed to the metaclass. Thus "),a("code",[s._v("class MyDummy(metaclass=mytype, x=2)")]),s._v(" will pass "),a("code",[s._v("x=2")]),s._v(" as a keyword argument to the "),a("code",[s._v("mytype")]),s._v(" constructor.")]),s._v(" "),a("p",[s._v("Read this "),a("a",{attrs:{href:"http://stackoverflow.com/questions/100003/what-is-a-metaclass-in-python/6581949#6581949",target:"_blank",rel:"noopener noreferrer"}},[s._v("in-depth description of python meta-classes"),a("OutboundLink")],1),s._v(" for more details.")]),s._v(" "),a("h2",{attrs:{id:"singletons-using-metaclasses"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#singletons-using-metaclasses"}},[s._v("#")]),s._v(" Singletons using metaclasses")]),s._v(" "),a("p",[s._v("A singleton is a pattern that restricts the instantiation of a class to one instance/object. For more info on python singleton design patterns, see "),a("a",{attrs:{href:"http://python-3-patterns-idioms-test.readthedocs.io/en/latest/Singleton.html",target:"_blank",rel:"noopener noreferrer"}},[s._v("here"),a("OutboundLink")],1),s._v(".")]),s._v(" "),a("div",{staticClass:"language-py extra-class"},[a("pre",{pre:!0,attrs:{class:"language-py"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("class")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("SingletonType")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[s._v("type")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(":")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("def")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("__call__")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),s._v("cls"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("*")]),s._v("args"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("**")]),s._v("kwargs"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(":")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("try")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(":")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("return")]),s._v(" cls"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),s._v("__instance\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("except")]),s._v(" AttributeError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(":")]),s._v("\n cls"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),s._v("__instance "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[s._v("super")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),s._v("SingletonType"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v(" cls"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),s._v("__call__"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("*")]),s._v("args"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("**")]),s._v("kwargs"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("return")]),s._v(" cls"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),s._v("__instance\n\n")])])]),a("div",{staticClass:"language-py extra-class"},[a("pre",{pre:!0,attrs:{class:"language-py"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("class")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("MySingleton")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[s._v("object")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(":")]),s._v("\n __metaclass__ "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" SingletonType\n\n")])])]),a("div",{staticClass:"language-py extra-class"},[a("pre",{pre:!0,attrs:{class:"language-py"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("class")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("MySingleton")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),s._v("metaclass"),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v("SingletonType"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(":")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("pass")]),s._v("\n\n")])])]),a("div",{staticClass:"language-py extra-class"},[a("pre",{pre:!0,attrs:{class:"language-py"}},[a("code",[s._v("MySingleton"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("is")]),s._v(" MySingleton"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("# True, only one instantiation occurs")]),s._v("\n\n")])])]),a("h2",{attrs:{id:"using-a-metaclass"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#using-a-metaclass"}},[s._v("#")]),s._v(" Using a metaclass")]),s._v(" "),a("h3",{attrs:{id:"metaclass-syntax"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#metaclass-syntax"}},[s._v("#")]),s._v(" Metaclass syntax")]),s._v(" "),a("div",{staticClass:"language-py extra-class"},[a("pre",{pre:!0,attrs:{class:"language-py"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("class")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("MyClass")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[s._v("object")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(":")]),s._v("\n __metaclass__ "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" SomeMetaclass\n\n")])])]),a("div",{staticClass:"language-py extra-class"},[a("pre",{pre:!0,attrs:{class:"language-py"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("class")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("MyClass")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),s._v("metaclass"),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v("SomeMetaclass"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(":")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("pass")]),s._v("\n\n")])])]),a("h3",{attrs:{id:"python-2-and-3-compatibility-with-six"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#python-2-and-3-compatibility-with-six"}},[s._v("#")]),s._v(" Python 2 and 3 compatibility with "),a("code",[s._v("six")])]),s._v(" "),a("div",{staticClass:"language-py extra-class"},[a("pre",{pre:!0,attrs:{class:"language-py"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("import")]),s._v(" six\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("class")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("MyClass")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),s._v("six"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),s._v("with_metaclass"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),s._v("SomeMetaclass"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(":")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("pass")]),s._v("\n\n")])])]),a("h2",{attrs:{id:"introduction-to-metaclasses"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#introduction-to-metaclasses"}},[s._v("#")]),s._v(" Introduction to Metaclasses")]),s._v(" "),a("h3",{attrs:{id:"what-is-a-metaclass"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#what-is-a-metaclass"}},[s._v("#")]),s._v(" What is a metaclass?")]),s._v(" "),a("p",[s._v("In Python, everything is an object: integers, strings, lists, even functions and classes themselves are objects. And every object is an instance of a class.")]),s._v(" "),a("p",[s._v("To check the class of an object x, one can call "),a("code",[s._v("type(x)")]),s._v(", so:")]),s._v(" "),a("div",{staticClass:"language-py extra-class"},[a("pre",{pre:!0,attrs:{class:"language-py"}},[a("code",[a("span",{pre:!0,attrs:{class:"token operator"}},[s._v(">>")]),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v(">")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[s._v("type")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[s._v("5")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n"),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("<")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[s._v("type")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[s._v("'int'")]),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v(">")]),s._v("\n"),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v(">>")]),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v(">")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[s._v("type")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[s._v("str")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n"),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("<")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[s._v("type")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[s._v("'type'")]),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v(">")]),s._v("\n"),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v(">>")]),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v(">")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[s._v("type")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("[")]),a("span",{pre:!0,attrs:{class:"token number"}},[s._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[s._v("2")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[s._v("3")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n"),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("<")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[s._v("type")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[s._v("'list'")]),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v(">")]),s._v("\n\n"),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v(">>")]),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v(">")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("class")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("C")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[s._v("object")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(":")]),s._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("pass")]),s._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),s._v("\n"),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v(">>")]),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v(">")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[s._v("type")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),s._v("C"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n"),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("<")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[s._v("type")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[s._v("'type'")]),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v(">")]),s._v(" \n\n")])])]),a("p",[s._v("Most classes in python are instances of "),a("code",[s._v("type")]),s._v(". "),a("code",[s._v("type")]),s._v(" itself is also a class. Such classes whose instances are also classes are called metaclasses.")]),s._v(" "),a("h3",{attrs:{id:"the-simplest-metaclass"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#the-simplest-metaclass"}},[s._v("#")]),s._v(" The Simplest Metaclass")]),s._v(" "),a("p",[s._v("OK, so there is already one metaclass in Python: "),a("code",[s._v("type")]),s._v(". Can we create another one?")]),s._v(" "),a("div",{staticClass:"language-py extra-class"},[a("pre",{pre:!0,attrs:{class:"language-py"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("class")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("SimplestMetaclass")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[s._v("type")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(":")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("pass")]),s._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("class")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("MyClass")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[s._v("object")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(":")]),s._v("\n __metaclass__ "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" SimplestMetaclass\n\n")])])]),a("p",[s._v("That does not add any functionality, but it is a new metaclass, see that MyClass is now an instance of SimplestMetaclass:")]),s._v(" "),a("div",{staticClass:"language-py extra-class"},[a("pre",{pre:!0,attrs:{class:"language-py"}},[a("code",[a("span",{pre:!0,attrs:{class:"token operator"}},[s._v(">>")]),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v(">")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[s._v("type")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),s._v("MyClass"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n"),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("<")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("class")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[s._v("'__main__.SimplestMetaclass'")]),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v(">")]),s._v("\n\n")])])]),a("h3",{attrs:{id:"a-metaclass-which-does-something"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#a-metaclass-which-does-something"}},[s._v("#")]),s._v(" A Metaclass which does Something")]),s._v(" "),a("p",[s._v("A metaclass which does something usually overrides "),a("code",[s._v("type")]),s._v("'s "),a("code",[s._v("__new__")]),s._v(", to modify some properties of the class to be created, before calling the original "),a("code",[s._v("__new__")]),s._v(" which creates the class:")]),s._v(" "),a("div",{staticClass:"language-py extra-class"},[a("pre",{pre:!0,attrs:{class:"language-py"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("class")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("AnotherMetaclass")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[s._v("type")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(":")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("def")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("__new__")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),s._v("cls"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v(" name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v(" parents"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v(" dct"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(":")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("# cls is this class")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("# name is the name of the class to be created")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("# parents is the list of the class's parent classes")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("# dct is the list of class's attributes (methods, static variables)")]),s._v("\n\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("# here all of the attributes can be modified before creating the class, e.g.")]),s._v("\n\n dct"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("[")]),a("span",{pre:!0,attrs:{class:"token string"}},[s._v("'x'")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("]")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[s._v("8")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("# now the class will have a static variable x = 8")]),s._v("\n\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("# return value is the new class. super will take care of that")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("return")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[s._v("super")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),s._v("AnotherMetaclass"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v(" cls"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),s._v("__new__"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),s._v("cls"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v(" name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v(" parents"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v(" dct"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n\n")])])]),a("h2",{attrs:{id:"custom-functionality-with-metaclasses"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#custom-functionality-with-metaclasses"}},[s._v("#")]),s._v(" Custom functionality with metaclasses")]),s._v(" "),a("p",[a("strong",[s._v("Functionality in metaclasses")]),s._v(" can be changed so that whenever a class is built, a string is printed to standard output, or an exception is thrown. This metaclass will print the name of the class being built.")]),s._v(" "),a("div",{staticClass:"language-py extra-class"},[a("pre",{pre:!0,attrs:{class:"language-py"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("class")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("VerboseMetaclass")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[s._v("type")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(":")]),s._v("\n\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("def")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("__new__")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),s._v("cls"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v(" class_name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v(" class_parents"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v(" class_dict"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(":")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("print")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[s._v('"Creating class "')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v(" class_name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n new_class "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[s._v("super")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),s._v("__new__"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),s._v("cls"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v(" class_name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v(" class_parents"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v(" class_dict"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("return")]),s._v(" new_class\n\n")])])]),a("p",[s._v("You can use the metaclass like so:")]),s._v(" "),a("div",{staticClass:"language-py extra-class"},[a("pre",{pre:!0,attrs:{class:"language-py"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("class")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("Spam")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),s._v("metaclass"),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v("VerboseMetaclass"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(":")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("def")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("eggs")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),s._v("self"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(":")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("print")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[s._v('"[insert example string here]"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\ns "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" Spam"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\ns"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),s._v("eggs"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n\n")])])]),a("p",[s._v("The standard output will be:")]),s._v(" "),a("div",{staticClass:"language-py extra-class"},[a("pre",{pre:!0,attrs:{class:"language-py"}},[a("code",[s._v("Creating "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("class")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("Spam")]),s._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("[")]),s._v("insert example string here"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("]")]),s._v("\n\n")])])]),a("h2",{attrs:{id:"the-default-metaclass"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#the-default-metaclass"}},[s._v("#")]),s._v(" The default metaclass")]),s._v(" "),a("p",[s._v("You may have heard that everything in Python is an object. It is true, and all objects have a class:")]),s._v(" "),a("div",{staticClass:"language-py extra-class"},[a("pre",{pre:!0,attrs:{class:"language-py"}},[a("code",[a("span",{pre:!0,attrs:{class:"token operator"}},[s._v(">>")]),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v(">")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[s._v("type")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[s._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n"),a("span",{pre:!0,attrs:{class:"token builtin"}},[s._v("int")]),s._v("\n\n")])])]),a("p",[s._v("The literal 1 is an instance of "),a("code",[s._v("int")]),s._v(". Lets declare a class:")]),s._v(" "),a("div",{staticClass:"language-py extra-class"},[a("pre",{pre:!0,attrs:{class:"language-py"}},[a("code",[a("span",{pre:!0,attrs:{class:"token operator"}},[s._v(">>")]),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v(">")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("class")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("Foo")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[s._v("object")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(":")]),s._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("pass")]),s._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),s._v("\n\n")])])]),a("p",[s._v("Now lets instantiate it:")]),s._v(" "),a("div",{staticClass:"language-py extra-class"},[a("pre",{pre:!0,attrs:{class:"language-py"}},[a("code",[a("span",{pre:!0,attrs:{class:"token operator"}},[s._v(">>")]),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v(">")]),s._v(" bar "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" Foo"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n\n")])])]),a("p",[s._v("What is the class of "),a("code",[s._v("bar")]),s._v("?")]),s._v(" "),a("div",{staticClass:"language-py extra-class"},[a("pre",{pre:!0,attrs:{class:"language-py"}},[a("code",[a("span",{pre:!0,attrs:{class:"token operator"}},[s._v(">>")]),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v(">")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[s._v("type")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),s._v("bar"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\nFoo\n\n")])])]),a("p",[s._v("Nice, "),a("code",[s._v("bar")]),s._v(" is an instance of "),a("code",[s._v("Foo")]),s._v(". But what is the class of "),a("code",[s._v("Foo")]),s._v(" itself?")]),s._v(" "),a("div",{staticClass:"language-py extra-class"},[a("pre",{pre:!0,attrs:{class:"language-py"}},[a("code",[a("span",{pre:!0,attrs:{class:"token operator"}},[s._v(">>")]),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v(">")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[s._v("type")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),s._v("Foo"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n"),a("span",{pre:!0,attrs:{class:"token builtin"}},[s._v("type")]),s._v("\n\n")])])]),a("p",[s._v("Ok, "),a("code",[s._v("Foo")]),s._v(" itself is an instance of "),a("code",[s._v("type")]),s._v(". How about "),a("code",[s._v("type")]),s._v(" itself?")]),s._v(" "),a("div",{staticClass:"language-py extra-class"},[a("pre",{pre:!0,attrs:{class:"language-py"}},[a("code",[a("span",{pre:!0,attrs:{class:"token operator"}},[s._v(">>")]),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v(">")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[s._v("type")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[s._v("type")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n"),a("span",{pre:!0,attrs:{class:"token builtin"}},[s._v("type")]),s._v("\n\n")])])]),a("p",[s._v("So what is a metaclass? For now lets pretend it is just a fancy name for the class of a class. Takeaways:")]),s._v(" "),a("ul",[a("li",[s._v("Everything is an object in Python, so everything has a class")]),s._v(" "),a("li",[s._v("The class of a class is called a metaclass")]),s._v(" "),a("li",[s._v("The default metaclass is "),a("code",[s._v("type")]),s._v(", and by far it is the most common metaclass")])]),s._v(" "),a("p",[s._v('But why should you know about metaclasses? Well, Python itself is quite "hackable", and the concept of metaclass is important if you are doing advanced stuff like meta-programming or if you want to control how your classes are initialized.')]),s._v(" "),a("h4",{attrs:{id:"remarks"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#remarks"}},[s._v("#")]),s._v(" Remarks")]),s._v(" "),a("p",[s._v("When designing your architecture, consider that many things which can be accomplished with metaclasses can also be accomplished using more simple semantics:")]),s._v(" "),a("ul",[a("li",[s._v("Traditional inheritance is often more than enough.")]),s._v(" "),a("li",[s._v("Class decorators can mix-in functionality into a classes on a ad-hoc approach.")]),s._v(" "),a("li",[s._v("Python 3.6 introduces "),a("code",[s._v("__init_subclass__()")]),s._v(" which allows a class to partake in the creation of its subclass.")])])])}),[],!1,null,null,null);t.default=e.exports}}]);