Skip to content

Instantly share code, notes, and snippets.

@jakab922
Last active May 5, 2018 19:27
Show Gist options
  • Save jakab922/6130481 to your computer and use it in GitHub Desktop.
Save jakab922/6130481 to your computer and use it in GitHub Desktop.
Python metaclass reminder
class MetaClass(type):
counter = 1
def __new__(meta, name, bases, dct):
""" Gets called when we read in the class definition for which this is the metaclass of"""
print "MetaClass.__new__(%s, %s, %s, %s)" % (meta, name, bases, dct)
dct['class_num'] = meta.counter
meta.counter += 1
return super(MetaClass, meta).__new__(meta, name, bases, dct)
def __init__(cls, name, bases, dct):
""" Gets called when we read in the class definition for which this is the metaclass of and after __new__
of the metaclass."""
print "MetaClass.__init__(%s, %s, %s, %s)" % (cls, name, bases, dct)
return super(MetaClass, cls).__init__(name, bases, dct)
def __call__(cls, *args, **kwargs):
""" Called when an object is created from the class of which this is a metaclass of. args,kwargs are the normal
init params"""
print "MetaClass.__call__(%s, %s, %s)" % (cls, args, kwargs)
return type.__call__(cls, *args, **kwargs)
class NormalClass(object):
__metaclass__ = MetaClass
def __new__(cls, *args, **kwargs):
""" Called when class is instantiated and after the metaclasses __call__ method. """
print "NormalClass.__new__(%s, %s, %s)" % (cls, args, kwargs)
return super(NormalClass, cls).__new__(cls, *args, **kwargs)
def __init__(self, *args, **kwargs):
""" Called after meta.__call__ and normal.__new__ on the class returned by __new__"""
print self.class_num
print "NormalClass.__init__(%s, %s, %s)" % (self, args, kwargs)
class OtherNormalClass(object):
__metaclass__ = MetaClass
def __new__(cls, *args, **kwargs):
print "OtherNormalClass.__new__(%s, %s, %s)" % (cls, args, kwargs)
return super(OtherNormalClass, cls).__new__(cls, *args, **kwargs)
def __init__(self, *args, **kwargs):
print self.class_num
print "OtherNormalClass.__init__(%s, %s, %s)" % (self, args, kwargs)
if __name__ == "__main__":
norm1 = NormalClass(5, a=2)
norm2 = NormalClass(6, a=3)
other1 = OtherNormalClass(7, a=12)
"""
Call orders with first params in brackets.
Call order on reading the class definition:
meta.__new__(meta), meta.__init__(class)
Call order on the class instantiation:
meta.__call__(class), class.__new__(class), class.__init__(self)
Call order when we call an instance:
class.__call__(self)
"""
"""TODO:
- Look up what the various methods should return and how does that effect the whole procedure.
- Maybe a full call graph to make this a bit cleaner.
"""
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment