Rolex Pearlmaster Replica
  Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
This article is part of in the series
Published: Friday 1st February 2013
Last Updated: Wednesday 29th December 2021

A metaclass is a class/object which defines a type/class of other classes. In Python a metaclass can be a class, function or any object that supports calling an interface. This is because to create a class object; its metaclass is called with the class name, base classes and attributes (methods). When no metaclass is defined (which is usually the case), the default metaclass type is used.

For example:



[python]
# Here __metaclass__ points to the metaclass object.
class ExampleClass(metaclass=type):
pass
[/python]


[python]
# Here __metaclass__ points to the metaclass object.
class ExampleClass(object):
__metaclass__ = type
pass
[/python]


When a class is created, the interpreter:

  1. Gets the name of the class.
  2. Gets the base classes of the class.
  3. Gets the metaclass of the class. If it is defined, it will use this first. Otherwise, it will check in the base classes for the metaclass. It it can't find a metaclass in the base class, the type object is used instead.
  4. Gets the variables/attributes in the class and stores them as a dictionary.
  5. Passes this information to metaclass as metaclass(name_of_class, base_classes, attributes_dictionary) and it returns a class object.

For example:

[python]
# type(name, base, attrs)
# name is the name of the class
# base is a tuple of base classes (all methods/attributes are inherited
# from these) attrs is a dictionary filled with the class attributes
classObject = type('ExampleClass', (object,) ,{})
[/python]

When type is called, its __call__ method is called. This method in turn calls the __new__ and __init__ methods. The __new__ method creates a new object, whereas the __init__ method initializes it. We can easily play with methods. This is a working example:



[python]
class a:
def __init__(self, data):
self.data = data

def getd3(self):
return self.data * 3

class MyMeta(type):
def __new__(metaname, classname, baseclasses, attrs):
print('New called with')
print('metaname', metaname)
print('classname', classname)
print('baseclasses', baseclasses)
print('attrs', attrs)
attrs['getdata'] = a.__dict__['getd3']
# attrs['getdata'] = a.getd3
return type.__new__(metaname, classname, baseclasses, attrs)

def __init__(classobject, classname, baseclasses, attrs):
print('init called with')
print('classobject', classobject)
print('classname', classname)
print('baseclasses', baseclasses)
print('attrs', attrs)

class Kls(metaclass=MyMeta):
def __init__(self,data):
self.data = data

def printd(self):
print(self.data)

ik = Kls('arun')
ik.printd()
print(ik.getdata())
[/python]

When running the code, we get:

[shell]
New called with
metaname <class '__main__.MyMeta'>
classname Kls
baseclasses ()
attrs {'__module__': '__main__', 'printd': <function printd at 0x7f3ebca86958>, '__init__': <function __init__ at 0x7f3ebca868d0>}
init called with
classobject <class '__main__.Kls'>
classname Kls
baseclasses ()
attrs {'__module__': '__main__', 'getdata': <function getd3 at 0x7f3ebca86408>, 'printd': <function printd at 0x7f3ebca86958>, '__init__': <function __init__ at 0x7f3ebca868d0>}
arun
arunarunarun
[/shell]


[python]
class a(object):
def __init__(self, data):
self.data = data

def getd3(self):
return self.data * 3

class MyMeta(type):
def __new__(metaname, classname, baseclasses, attrs):
print 'New called with'
print 'metaname', metaname
print 'classname', classname
print 'baseclasses', baseclasses
print 'attrs', attrs
attrs['getdata'] = a.__dict__['getd3']
# attrs['getdata'] = a.getd3
return type.__new__(metaname, classname, baseclasses, attrs)

def __init__(classobject, classname, baseclasses, attrs):
print 'init called with'
print 'classobject', classobject
print 'classname', classname
print 'baseclasses', baseclasses
print 'attrs', attrs

class Kls(object):
__metaclass__ = MyMeta

def __init__(self, data):
self.data = data

def printd(self):
print self.data

ik = Kls('arun')
ik.printd()
print ik.getdata()
[/python]

When running the code, we get:

[shell]
New called with
metaname <class '__main__.MyMeta'>
classname Kls
baseclasses (<type 'object'>,)
attrs {'__module__': '__main__', '__metaclass__': <class '__main__.MyMeta'>, 'printd': <function printd at 0x7fbdab0176e0>, '__init__': <function __init__ at 0x7fbdab017668>}
init called with
classobject <class '__main__.Kls'>
classname Kls
baseclasses (<type 'object'>,)
attrs {'__module__': '__main__', 'getdata': <function getd3 at 0x7fbdab017500>, '__metaclass__': <class '__main__.MyMeta'>, 'printd': <function printd at 0x7fbdab0176e0>, '__init__': <function __init__ at 0x7fbdab017668>}
arun
arunarunarun
[/shell]


Normally we need to override only one method __new__ or __init__. We can also use function instead of a class. Here is an example:



[python]
def meta_func(name, bases, attrs):
print('meta function called with', name, bases, attrs)
nattrs = {'mod' + key:attrs[key] for key in attrs}
return type(name, bases, nattrs)

MyMeta = meta_func

class Kls(metaclass=MyMeta):
def setd(self, data):
self.data = data

def getd(self):
return self.data

k = Kls()
k.modsetd('arun')
print(k.modgetd())
[/python]

Gives us the following output:

[shell]
meta function called with Kls () {'setd': <function setd at 0x7f3bafe7cd10>, '__module__': '__main__', 'getd': <function getd at 0x7f3bafe7cd98>}
arun
[/shell]



[python]
def meta_func(name, bases, attrs):
print 'meta function called with', name, bases, attrs
nattrs = {'mod' + key:attrs[key] for key in attrs}
return type(name, bases, nattrs)

MyMeta = meta_func

class Kls(object):
__metaclass__ = MyMeta

def setd(self, data):
self.data = data

def getd(self):
return self.data

k = Kls()
k.modsetd('arun')
print k.modgetd()
[/python]

Gives us the following output:

[shell]
meta function called with Kls (<type 'object'>,) {'setd': <function setd at 0x88b21ec>, 'getd': <function getd at 0x88b22cc>, '__module__': '__main__', '__metaclass__': <function meta_func at 0xb72341b4>}
arun
[/shell]


Other then modifying base classes and methods of classes to be created, metaclasses can also modify instance creation process. This is because when we create an instance (ik = Kls()), this is like calling the class Kls. One point to note is that whenever we call an object its type's __call__ method is called. So in this case the class type is metaclass hence its __call__ method will be called. We can check like this:



[python]
class MyMeta(type):
def __call__(clsname, *args):
print('MyMeta called with')
print('clsname:', clsname)
print('args:', args)
instance = object.__new__(clsname)
instance.__init__(*args)
return instance

class Kls(metaclass=MyMeta):
def __init__(self, data):
self.data = data

def printd(self):
print(self.data)

ik = Kls('arun')
ik.printd()
[/python]



[python]
class MyMeta(type):
def __call__(clsname, *args):
print 'MyMeta called with'
print 'clsname:', clsname
print 'args:' ,args
instance = object.__new__(clsname)
instance.__init__(*args)
return instance

class Kls(object):
__metaclass__ = MyMeta

def __init__(self,data):
self.data = data

def printd(self):
print self.data

ik = Kls('arun')
ik.printd()
[/python]


The output is as follows:

[shell]
MyMeta called with
clsname: <class '__main__.Kls'>
args: ('arun',)
arun
[/shell]

Equipped with this information, if we go to the start of our discussion about the class creation process, it ended with a call to the metaclass object, which provided a class object. It was like this:

[python]
Kls = MetaClass(name, bases, attrs)
[/python]

Hence this call should call the metaclass's type. The metaclass type is the metaclass's metaclass! We can check this as follows:



[python]
class SuperMeta(type):
def __call__(metaname, clsname, baseclasses, attrs):
print('SuperMeta Called')
clsob = type.__new__(metaname, clsname, baseclasses, attrs)
type.__init__(clsob, clsname, baseclasses, attrs)
return clsob

class MyMeta(type, metaclass=SuperMeta):
def __call__(cls, *args, **kwargs):
print('MyMeta called', cls, args, kwargs)
ob = object.__new__(cls, *args)
ob.__init__(*args)
return ob

print('create class')

class Kls(metaclass=MyMeta):
def __init__(self, data):
self.data = data

def printd(self):
print(self.data)

print('class created')
ik = Kls('arun')
ik.printd()
ik2 = Kls('avni')
ik2.printd()
[/python]



[python]
class SuperMeta(type):
def __call__(metaname, clsname, baseclasses, attrs):
print 'SuperMeta Called'
clsob = type.__new__(metaname, clsname, baseclasses, attrs)
type.__init__(clsob, clsname, baseclasses, attrs)
return clsob

class MyMeta(type):
__metaclass__ = SuperMeta
def __call__(cls, *args, **kwargs):
print 'MyMeta called', cls, args, kwargs
ob = object.__new__(cls, *args)
ob.__init__(*args)
return ob

print 'create class'

class Kls(object):
__metaclass__ = MyMeta

def __init__(self, data):
self.data = data

def printd(self):
print self.data

print 'class created'

ik = Kls('arun')
ik.printd()
ik2 = Kls('avni')
ik2.printd()
[/python]


Gives us the following output:

[shell]
create class
SuperMeta Called
class created
MyMeta called class '__main__.Kls' ('arun',) {}
arun
MyMeta called &lt;class '__main__.Kls' ('avni',) {}
avni
[/shell]

About The Author

Arun Tigeraniya

Latest Articles


Tags

  • Unpickling
  • array
  • sorting
  • reversal
  • Python salaries
  • list sort
  • Pip
  • .groupby()
  • pyenv global
  • NumPy arrays
  • Modulo
  • OpenCV
  • Torrent
  • data
  • int function
  • file conversion
  • calculus
  • python typing
  • encryption
  • strings
  • big o calculator
  • gamin
  • HTML
  • list
  • insertion sort
  • in place reversal
  • learn python
  • String
  • python packages
  • FastAPI
  • argparse
  • zeros() function
  • AWS Lambda
  • Scikit Learn
  • Free
  • classes
  • turtle
  • convert file
  • abs()
  • python do while
  • set operations
  • data visualization
  • efficient coding
  • data analysis
  • HTML Parser
  • circular queue
  • effiiciency
  • Learning
  • windows
  • reverse
  • Python IDE
  • python maps
  • dataframes
  • Num Py Zeros
  • Python Lists
  • Fprintf
  • Version
  • immutable
  • python turtle
  • pandoc
  • semantic kernel
  • do while
  • set
  • tabulate
  • optimize code
  • object oriented
  • HTML Extraction
  • head
  • selection sort
  • Programming
  • install python on windows
  • reverse string
  • python Code Editors
  • Pytest
  • pandas.reset_index
  • NumPy
  • Infinite Numbers in Python
  • Python Readlines()
  • Trial
  • youtube
  • interactive
  • deep
  • kernel
  • while loop
  • union
  • tutorials
  • audio
  • github
  • Parsing
  • tail
  • merge sort
  • Programming language
  • remove python
  • concatenate string
  • Code Editors
  • unittest
  • reset_index()
  • Train Test Split
  • Local Testing Server
  • Python Input
  • Studio
  • excel
  • sgd
  • deeplearning
  • pandas
  • class python
  • intersection
  • logic
  • pydub
  • git
  • Scrapping
  • priority queue
  • quick sort
  • web development
  • uninstall python
  • python string
  • code interface
  • PyUnit
  • round numbers
  • train_test_split()
  • Flask module
  • Software
  • FL
  • llm
  • data science
  • testing
  • pathlib
  • oop
  • gui
  • visualization
  • audio edit
  • requests
  • stack
  • min heap
  • Linked List
  • machine learning
  • scripts
  • compare string
  • time delay
  • PythonZip
  • pandas dataframes
  • arange() method
  • SQLAlchemy
  • Activator
  • Music
  • AI
  • ML
  • import
  • file
  • jinja
  • pysimplegui
  • notebook
  • decouple
  • queue
  • heapify
  • Singly Linked List
  • intro
  • python scripts
  • learning python
  • python bugs
  • ZipFunction
  • plus equals
  • np.linspace
  • SQLAlchemy advance
  • Download
  • No
  • nlp
  • machiine learning
  • dask
  • file management
  • jinja2
  • ui
  • tdqm
  • configuration
  • deque
  • heap
  • Data Structure
  • howto
  • dict
  • csv in python
  • logging in python
  • Python Counter
  • python subprocess
  • numpy module
  • Python code generators
  • KMS
  • Office
  • modules
  • web scraping
  • scalable
  • pipx
  • templates
  • python not
  • pytesseract
  • env
  • push
  • search
  • Node
  • python tutorial
  • dictionary
  • csv file python
  • python logging
  • Counter class
  • Python assert
  • linspace
  • numbers_list
  • Tool
  • Key
  • automation
  • website data
  • autoscale
  • packages
  • snusbase
  • boolean
  • ocr
  • pyside6
  • pop
  • binary search
  • Insert Node
  • Python tips
  • python dictionary
  • Python's Built-in CSV Library
  • logging APIs
  • Constructing Counters
  • Assertions
  • Matplotlib Plotting
  • any() Function
  • Activation
  • Patch
  • threading
  • scrapy
  • game analysis
  • dependencies
  • security
  • not operation
  • pdf
  • build gui
  • dequeue
  • linear search
  • Add Node
  • Python tools
  • function
  • python update
  • logging module
  • Concatenate Data Frames
  • python comments
  • matplotlib
  • Recursion Limit
  • License
  • Pirated
  • square root
  • website extract python
  • steamspy
  • processing
  • cybersecurity
  • variable
  • image processing
  • incrementing
  • Data structures
  • algorithm
  • Print Node
  • installation
  • python function
  • pandas installation
  • Zen of Python
  • concatenation
  • Echo Client
  • Pygame
  • NumPy Pad()
  • Unlock
  • Bypass
  • pytorch
  • zipp
  • steam
  • multiprocessing
  • type hinting
  • global
  • argh
  • c vs python
  • Python
  • stacks
  • Sort
  • algorithms
  • install python
  • Scopes
  • how to install pandas
  • Philosophy of Programming
  • concat() function
  • Socket State
  • % Operator
  • Python YAML
  • Crack
  • Reddit
  • lightning
  • zip files
  • python reduce
  • library
  • dynamic
  • local
  • command line
  • define function
  • Pickle
  • enqueue
  • ascending
  • remove a node
  • Django
  • function scope
  • Tuple in Python
  • pandas groupby
  • pyenv
  • socket programming
  • Python Modulo
  • Dictionary Update()
  • Hack
  • sdk
  • python automation
  • main
  • reduce
  • typing
  • ord
  • print
  • network
  • matplotlib inline
  • Pickling
  • datastructure
  • bubble sort
  • find a node
  • Flask
  • calling function
  • tuple
  • GroupBy method
  • Pythonbrew
  • Np.Arange()
  • Modulo Operator
  • Python Or Operator
  • Keygen
  • cloud
  • pyautogui
  • python main
  • reduce function
  • type hints
  • python ord
  • format
  • python socket
  • jupyter
  • Python is a beautiful language.