Skip to content

Instantly share code, notes, and snippets.

@andreadipersio
Last active December 30, 2015 11:59
Show Gist options
  • Save andreadipersio/7826509 to your computer and use it in GitHub Desktop.
Save andreadipersio/7826509 to your computer and use it in GitHub Desktop.
An example on how to use metaclasses, difference between python 2 and python 3 and using six to write code supported on both.
METACLASS_TXT = """
Hello, I am {} metaclass!
I am now creating '{}' class, child of '{}',
having the following class attributes:
{}
"""
class OCPRobotMeta(type):
def __new__(cls, name, bases, attrs):
"""new is called for the creation of a new class"""
print(METACLASS_TXT.format(cls, name, bases, attrs))
return super(OCPRobotMeta, cls).__new__(cls, name, bases, attrs)
class Robocop(object):
__metaclass__ = OCPRobotMeta
prime_directives = ["Serve the public trust",
"Protect the innocent",
"Uphold the law"]
class Robocop2014(Robocop):
pass
class ED209(object):
__metaclass__ = OCPRobotMeta
class T800(object):
pass
if __name__ == "__main__":
robots = [Robocop(), Robocop2014(), ED209(), T800()]
for r in robots:
if isinstance(r.__class__, OCPRobotMeta):
print "{} is a fine product of OCP Corp.".format(r.__class__)
else:
print "{} is not an OCP Corp. products".format(r.__class__)
"""
Output
Hello, I am <class '__main__.OCPRobotMeta'> metaclass!
I am now creating 'Robocop' class, child of '(<type 'object'>,)',
having the following class attributes:
{'__module__': '__main__', '__metaclass__': <class '__main__.OCPRobotMeta'>,
'prime_directives': ['Serve the public thrust', 'Protect the innocent', 'Uphold the law']}
Hello, I am <class '__main__.OCPRobotMeta'> metaclass!
I am now creating 'Robocop2014' class, child of '(<class '__main__.Robocop'>,)',
having the following class attributes:
{'__module__': '__main__'}
Hello, I am <class '__main__.OCPRobotMeta'> metaclass!
I am now creating 'ED209' class, child of '(<type 'object'>,)',
having the following class attributes:
{'__module__': '__main__', '__metaclass__': <class '__main__.OCPRobotMeta'>}
<class '__main__.Robocop'> is a fine product of OCP Corp.
<class '__main__.Robocop2014'> is a fine product of OCP Corp.
<class '__main__.ED209'> is a fine product of OCP Corp.
<class '__main__.T800'> is not an OCP Corp. products
"""
METACLASS_TXT = """
Hello, I am {} metaclass!
I am now creating '{}' class, child of '{}',
having the following class attributes:
{}
"""
class OCPRobotMeta(type):
def __new__(cls, name, bases, attrs):
"""new is called for the creation of a new class"""
print(METACLASS_TXT.format(cls, name, bases, attrs))
return super(OCPRobotMeta, cls).__new__(cls, name, bases, attrs)
class Robocop(metaclass=OCPRobotMeta):
prime_directives = ["Serve the public trust",
"Protect the innocent",
"Uphold the law"]
class Robocop2014(Robocop):
pass
class ED209(metaclass=OCPRobotMeta):
pass
class T800:
pass
if __name__ == "__main__":
robots = [Robocop(), Robocop2014(), ED209(), T800()]
for r in robots:
if isinstance(r.__class__, OCPRobotMeta):
print("{} is a fine product of OCP Corp.".format(r.__class__))
else:
print("{} is not an OCP Corp. products".format(r.__class__))
"""
Output
Hello, I am <class '__main__.OCPRobotMeta'> metaclass!
I am now creating 'Robocop' class, child of '()',
having the following class attributes:
{'prime_directives': ['Serve the public thrust', 'Protect the innocent',
'Uphold the law'], '__module__': '__main__', '__qualname__': 'Robocop'}
Hello, I am <class '__main__.OCPRobotMeta'> metaclass!
I am now creating 'Robocop2014' class, child of '(<class '__main__.Robocop'>,)',
having the following class attributes:
{'__module__': '__main__', '__qualname__': 'Robocop2014'}
Hello, I am <class '__main__.OCPRobotMeta'> metaclass!
I am now creating 'ED209' class, child of '()',
having the following class attributes:
{'__module__': '__main__', '__qualname__': 'ED209'}
<class '__main__.Robocop'> is a fine product of OCP Corp.
<class '__main__.Robocop2014'> is a fine product of OCP Corp.
<class '__main__.ED209'> is a fine product of OCP Corp.
<class '__main__.T800'> is not an OCP Corp. products
"""
import six
METACLASS_TXT = """
Hello, I am {} metaclass!
I am now creating '{}' class, child of '{}',
having the following class attributes:
{}
"""
class OCPRobotMeta(type):
def __new__(cls, name, bases, attrs):
"""new is called for the creation of a new class"""
super_new = super(OCPRobotMeta, cls).__new__
# six.with_metaclass() inserts an extra class called 'NewBase' in the
# inheritance tree: Model -> NewBase -> object. But the initialization
# should be executed only once for a given model class.
# attrs will never be empty for classes declared in the standard way
# (ie. with the `class` keyword). This is quite robust.
if name == 'NewBase' and attrs == {}:
return super_new(cls, name, bases, attrs)
print(METACLASS_TXT.format(cls, name, bases, attrs))
return super_new(cls, name, bases, attrs)
class Robocop(six.with_metaclass(OCPRobotMeta)):
prime_directives = ["Serve the public trust",
"Protect the innocent",
"Uphold the law"]
class Robocop2014(Robocop):
pass
class ED209(six.with_metaclass(OCPRobotMeta)):
pass
class T800:
pass
if __name__ == "__main__":
robots = [Robocop(), Robocop2014(), ED209(), T800()]
for r in robots:
if isinstance(r.__class__, OCPRobotMeta):
print("{} is a fine product of OCP Corp.".format(r.__class__))
else:
print("{} is not an OCP Corp. products".format(r.__class__))
"""
Output (works both on python2 and python3)
Hello, I am <class '__main__.OCPRobotMeta'> metaclass!
I am now creating 'Robocop' class, child of '()',
having the following class attributes:
{'prime_directives': ['Serve the public thrust', 'Protect the innocent',
'Uphold the law'], '__module__': '__main__', '__qualname__': 'Robocop'}
Hello, I am <class '__main__.OCPRobotMeta'> metaclass!
I am now creating 'Robocop2014' class, child of '(<class '__main__.Robocop'>,)',
having the following class attributes:
{'__module__': '__main__', '__qualname__': 'Robocop2014'}
Hello, I am <class '__main__.OCPRobotMeta'> metaclass!
I am now creating 'ED209' class, child of '()',
having the following class attributes:
{'__module__': '__main__', '__qualname__': 'ED209'}
<class '__main__.Robocop'> is a fine product of OCP Corp.
<class '__main__.Robocop2014'> is a fine product of OCP Corp.
<class '__main__.ED209'> is a fine product of OCP Corp.
<class '__main__.T800'> is not an OCP Corp. products
"""
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment