Last active
December 11, 2018 16:19
-
-
Save theavey/bddb611fd5d846de932263ac63e7d57c to your computer and use it in GitHub Desktop.
Use a metaclass to self-register subclasses to easily instatiate new objects and use an abstract base class
This file contains 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
{ | |
"cells": [ | |
{ | |
"cell_type": "code", | |
"execution_count": 3, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"from abc import abstractmethod, ABCMeta" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 19, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"class DynamicsMeta(ABCMeta):\n", | |
" def __init__(cls, name, bases, dct):\n", | |
" if not hasattr(cls, 'registry'):\n", | |
" cls.registry = {}\n", | |
" else:\n", | |
" dyn_id = name.lower()\n", | |
" cls.registry[dyn_id] = cls\n", | |
" super(DynamicsMeta, cls).__init__(name, bases, dct)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 20, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"class Dynamics(metaclass=DynamicsMeta):\n", | |
" \n", | |
" @abstractmethod\n", | |
" def density_matrix(self):\n", | |
" pass\n", | |
" \n", | |
" @abstractmethod\n", | |
" def time_step(self):\n", | |
" pass\n", | |
" \n", | |
" @classmethod\n", | |
" def make_new(self, kind, *args, **kwargs):\n", | |
" return self.registry[kind](*args, **kwargs)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 21, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"class PLDM(Dynamics):\n", | |
" def __init__(self, *args, **kwargs):\n", | |
" self.args = args\n", | |
" self.kwargs = kwargs\n", | |
" \n", | |
" def density_matrix(self):\n", | |
" return 'PLDM density matrix'\n", | |
" \n", | |
" def time_step(self):\n", | |
" return 'Advanced PLDM time'\n", | |
"\n", | |
"class IPLDM(Dynamics):\n", | |
" def __init__(self, *args, **kwargs):\n", | |
" self.args = args\n", | |
" self.kwargs = kwargs\n", | |
" \n", | |
" def density_matrix(self):\n", | |
" return 'IPLDM density matrix'\n", | |
" \n", | |
" def time_step(self):\n", | |
" return 'Advanced IPLDM time'\n", | |
"\n", | |
"class Broken(Dynamics):\n", | |
" def __init__(self, *args, **kwargs):\n", | |
" self.args = args\n", | |
" self.kwargs = kwargs\n", | |
" \n", | |
" def density_matrix(self):\n", | |
" return 'Broken density matrix'\n", | |
" " | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 22, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"PLDM density matrix\n" | |
] | |
} | |
], | |
"source": [ | |
"pldm = Dynamics.make_new('pldm')\n", | |
"print(pldm.density_matrix())" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 23, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"ename": "TypeError", | |
"evalue": "Can't instantiate abstract class Broken with abstract methods time_step", | |
"output_type": "error", | |
"traceback": [ | |
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", | |
"\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", | |
"\u001b[0;32m<ipython-input-23-13055d4f9720>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mbroke\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mDynamics\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmake_new\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'broken'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", | |
"\u001b[0;32m<ipython-input-20-942ed3c02c9c>\u001b[0m in \u001b[0;36mmake_new\u001b[0;34m(self, kind, *args, **kwargs)\u001b[0m\n\u001b[1;32m 11\u001b[0m \u001b[0;34m@\u001b[0m\u001b[0mclassmethod\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 12\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mmake_new\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mkind\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 13\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mregistry\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mkind\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", | |
"\u001b[0;31mTypeError\u001b[0m: Can't instantiate abstract class Broken with abstract methods time_step" | |
] | |
} | |
], | |
"source": [ | |
"broke = Dynamics.make_new('broken')" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [] | |
} | |
], | |
"metadata": { | |
"kernelspec": { | |
"display_name": "Python 3", | |
"language": "python", | |
"name": "python3" | |
}, | |
"language_info": { | |
"codemirror_mode": { | |
"name": "ipython", | |
"version": 3 | |
}, | |
"file_extension": ".py", | |
"mimetype": "text/x-python", | |
"name": "python", | |
"nbconvert_exporter": "python", | |
"pygments_lexer": "ipython3", | |
"version": "3.7.1" | |
} | |
}, | |
"nbformat": 4, | |
"nbformat_minor": 2 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment