Last active
December 30, 2015 11:59
-
-
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
""" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
""" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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