Last active
September 23, 2016 01:13
-
-
Save abravalheri/50955f6c3af91063280f0ddac04ed2eb to your computer and use it in GitHub Desktop.
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": 1, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"--- metaclass ---\n" | |
] | |
} | |
], | |
"source": [ | |
"print '--- metaclass ---'\n", | |
"class Meta(type):\n", | |
" def __new__(mcs, name, bases, attrs):\n", | |
" \"\"\"Meta.__new__\"\"\"\n", | |
" print 'Meta.__new__', mcs, name, bases, attrs\n", | |
"\n", | |
" # create properties dynamically\n", | |
" properties = attrs.pop('properties', [])\n", | |
" for prop in properties:\n", | |
" attrs[prop] = prop # make a property!\n", | |
"\n", | |
" return super(Meta, mcs).__new__(mcs, name, bases, attrs)\n", | |
" \n", | |
" def __init__(cls, name, bases, attrs):\n", | |
" \"\"\"Meta.__init__\"\"\"\n", | |
" print 'Meta.__init__', cls, name, bases, attrs\n", | |
" super(Meta, cls).__init__(name, bases, attrs)\n", | |
" \n", | |
" def __call__(cls, *args, **kwargs):\n", | |
" \"\"\"Meta.__call__\"\"\"\n", | |
" print 'Meta.__call__', cls, args, kwargs\n", | |
" \n", | |
" properties = kwargs.pop('properties', [])\n", | |
" if isinstance(properties, str):\n", | |
" properties = properties.split()\n", | |
" \n", | |
" # `properties` not passed... Use default behavior\n", | |
" if not properties:\n", | |
" return super(Meta, cls).__call__(*args, **kwargs)\n", | |
" \n", | |
" # Special behavior: construct a new class with `properties` attr\n", | |
" metaclass = cls.__class__\n", | |
" print '<<< BEGIN temporary class'\n", | |
" temp_class = metaclass(cls.__name__, (cls,), dict(properties=properties))\n", | |
" print '>>> END temporary class'\n", | |
" \n", | |
" return temp_class" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 2, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"--- class ---\n", | |
"Meta.__new__ <class '__main__.Meta'> AClass (<type 'object'>,) {'__module__': '__main__', '__metaclass__': <class '__main__.Meta'>}\n", | |
"Meta.__init__ <class '__main__.AClass'> AClass (<type 'object'>,) {'__module__': '__main__', '__metaclass__': <class '__main__.Meta'>}\n" | |
] | |
} | |
], | |
"source": [ | |
"print '--- class ---'\n", | |
"class AClass(object):\n", | |
" __metaclass__ = Meta" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 3, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"T.__new__(S, ...) -> a new object with type S, a subtype of T\n" | |
] | |
} | |
], | |
"source": [ | |
"print AClass.__new__.__doc__" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 4, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"--- object ---\n", | |
"Meta.__call__ <class '__main__.AClass'> () {}\n", | |
"<class '__main__.AClass'>\n" | |
] | |
} | |
], | |
"source": [ | |
"print '--- object ---'\n", | |
"anobject = AClass()\n", | |
"print type(anobject)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 5, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"--- class ---\n", | |
"Meta.__call__ <class '__main__.AClass'> () {'properties': ['a', 'b']}\n", | |
"<<< BEGIN temporary class\n", | |
"Meta.__new__ <class '__main__.Meta'> AClass (<class '__main__.AClass'>,) {'properties': ['a', 'b']}\n", | |
"Meta.__init__ <class '__main__.AClass'> AClass (<class '__main__.AClass'>,) {'a': 'a', 'b': 'b'}\n", | |
">>> END temporary class\n", | |
"<class '__main__.Meta'>\n" | |
] | |
} | |
], | |
"source": [ | |
"print '--- class ---'\n", | |
"AnotherClass = AClass(properties=['a', 'b'])\n", | |
"print type(AnotherClass)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 6, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"--- object ---\n", | |
"Meta.__call__ <class '__main__.AClass'> () {}\n", | |
"<class '__main__.AClass'>\n", | |
"a\n", | |
"b\n" | |
] | |
} | |
], | |
"source": [ | |
"print '--- object ---'\n", | |
"x = AnotherClass()\n", | |
"print type(x)\n", | |
"print x.a\n", | |
"print x.b" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 7, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"--- class ---\n", | |
"Meta.__new__ <class '__main__.Meta'> YetAnotherClass (<class '__main__.AClass'>,) {'__module__': '__main__', 'properties': ['c', 'd']}\n", | |
"Meta.__init__ <class '__main__.YetAnotherClass'> YetAnotherClass (<class '__main__.AClass'>,) {'__module__': '__main__', 'c': 'c', 'd': 'd'}\n", | |
"--- object ---\n", | |
"Meta.__call__ <class '__main__.YetAnotherClass'> () {}\n", | |
"c\n", | |
"d\n" | |
] | |
} | |
], | |
"source": [ | |
"print '--- class ---'\n", | |
"class YetAnotherClass(AClass):\n", | |
" properties = ['c', 'd']\n", | |
"\n", | |
"print '--- object ---'\n", | |
"yetanotherobject = YetAnotherClass()\n", | |
"print yetanotherobject.c\n", | |
"print yetanotherobject.d" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 8, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"--- class ---\n", | |
"Meta.__call__ <class '__main__.AClass'> () {'properties': ['e', 'f']}\n", | |
"<<< BEGIN temporary class\n", | |
"Meta.__new__ <class '__main__.Meta'> AClass (<class '__main__.AClass'>,) {'properties': ['e', 'f']}\n", | |
"Meta.__init__ <class '__main__.AClass'> AClass (<class '__main__.AClass'>,) {'e': 'e', 'f': 'f'}\n", | |
">>> END temporary class\n", | |
"Meta.__new__ <class '__main__.Meta'> OneMoreClass (<class '__main__.AClass'>,) {'__module__': '__main__'}\n", | |
"Meta.__init__ <class '__main__.OneMoreClass'> OneMoreClass (<class '__main__.AClass'>,) {'__module__': '__main__'}\n", | |
"--- object ---\n", | |
"Meta.__call__ <class '__main__.OneMoreClass'> () {}\n", | |
"e\n", | |
"f\n" | |
] | |
} | |
], | |
"source": [ | |
"print '--- class ---'\n", | |
"class OneMoreClass(AClass(properties=['e', 'f'])):\n", | |
" pass\n", | |
"\n", | |
"\n", | |
"print '--- object ---'\n", | |
"onemoreobject = OneMoreClass()\n", | |
"print onemoreobject.e\n", | |
"print onemoreobject.f" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": true | |
}, | |
"outputs": [], | |
"source": [] | |
} | |
], | |
"metadata": { | |
"kernelspec": { | |
"display_name": "Python 2", | |
"language": "python", | |
"name": "python2" | |
}, | |
"language_info": { | |
"codemirror_mode": { | |
"name": "ipython", | |
"version": 2 | |
}, | |
"file_extension": ".py", | |
"mimetype": "text/x-python", | |
"name": "python", | |
"nbconvert_exporter": "python", | |
"pygments_lexer": "ipython2", | |
"version": "2.7.11" | |
}, | |
"widgets": { | |
"state": {}, | |
"version": "1.1.2" | |
} | |
}, | |
"nbformat": 4, | |
"nbformat_minor": 0 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment