Created
February 2, 2016 01:07
-
-
Save johnpauljanecek/1e767022198dcc7e45d7 to your computer and use it in GitHub Desktop.
Blog notebooks
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
{ | |
"cells": [ | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Code for blog post on Save time creating classmethods using a metaclass\n", | |
"http://johnpauljanecek.work/blog/creating-classmethods-using-a-metaclass/" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"# Verify that classes are in fact just fancy dictionaries" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 6, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"from pprint import pprint as pp" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 21, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"'Foo.__dict__'\n", | |
"mappingproxy({'__doc__': None, '__weakref__': <attribute '__weakref__' of 'Foo' objects>, 'a_class_variable': 'a', 'a_function': <function Foo.a_function at 0x7fb358f79488>, '__dict__': <attribute '__dict__' of 'Foo' objects>, '__module__': '__main__'})\n", | |
"'pretty Foo'\n", | |
"'Pretty Foo.__dict__'\n", | |
"{'__dict__': <attribute '__dict__' of 'Foo' objects>,\n", | |
" '__doc__': None,\n", | |
" '__module__': '__main__',\n", | |
" '__weakref__': <attribute '__weakref__' of 'Foo' objects>,\n", | |
" 'a_class_variable': 'a',\n", | |
" 'a_function': <function Foo.a_function at 0x7fb358f79488>}\n" | |
] | |
} | |
], | |
"source": [ | |
"class Foo(object):\n", | |
" a_class_variable = \"a\"\n", | |
" def a_function(self):\n", | |
" print(a_function)\n", | |
" \n", | |
"pp(\"Foo.__dict__\")\n", | |
"pp(Foo.__dict__)\n", | |
"pp(\"pretty Foo\")\n", | |
"pp(\"Pretty Foo.__dict__\")\n", | |
"pp(dict(Foo.__dict__)) #convert it to a dictionary so pp dumps it out nice" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 38, | |
"metadata": { | |
"collapsed": false, | |
"scrolled": true | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"('__new__ \\n'\n", | |
" \" cls => <class '__main__.BarMetaClass'> \\n\"\n", | |
" \" name => 'Bar' \\n\"\n", | |
" \" bases => (<class 'object'>,) \\n\"\n", | |
" \" dct => {'__qualname__': 'Bar', 'a_class_variable': 'a', '__module__': \"\n", | |
" \"'__main__', 'a_function': <function Bar.a_function at 0x7fb358f43598>}\")\n", | |
"('__init__ \\n'\n", | |
" \" cls => <class '__main__.Bar'> \\n\"\n", | |
" \" name => 'Bar' \\n\"\n", | |
" \" bases => (<class 'object'>,) \\n\"\n", | |
" \" dct => {'__qualname__': 'Bar', 'a_class_variable': 'a', '__module__': \"\n", | |
" \"'__main__', 'a_function': <function Bar.a_function at 0x7fb358f43598>}\")\n" | |
] | |
} | |
], | |
"source": [ | |
"class BarMetaClass(type):\n", | |
" def __new__(cls, name,bases, dct):\n", | |
" #this is called before the class has been created\n", | |
" pp(\"__new__ \\n cls => %r \\n name => %r \\n bases => %r \\n dct => %r\" % (cls,name,bases,dct))\n", | |
" #the parent __new__ metaclass has to be returned\n", | |
" return type.__new__(cls,name, bases, dct)\n", | |
" \n", | |
" def __init__(cls, name,bases, dct):\n", | |
" #the parent __init__ metaclass method has to be called\n", | |
" type.__init__(cls,name, bases, dct)\n", | |
" #this is called after the class has been created\n", | |
" pp(\"__init__ \\n cls => %r \\n name => %r \\n bases => %r \\n dct => %r\" % (cls,name,bases,dct))\n", | |
" \n", | |
"\n", | |
"class Bar(object,metaclass = BarMetaClass):\n", | |
" a_class_variable = \"a\"\n", | |
" def a_function(self):\n", | |
" print(a_function)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"# adding a method and variable to class Foo using FooMetaClass" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 44, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"'testing out foo'\n", | |
"\"Foo.my_variable => 'my_variable'\"\n", | |
"\"foo.my_function() => 'from my function'\"\n" | |
] | |
} | |
], | |
"source": [ | |
"def my_function(self):\n", | |
" return \"from my function\"\n", | |
"\n", | |
"class FooMetaClass(type):\n", | |
" def __new__(cls, name,bases, dct):\n", | |
" dct[\"my_function\"] = my_function\n", | |
" dct[\"my_variable\"] = \"my_variable\"\n", | |
" #the parent __new__ metaclass has to be returned\n", | |
" return type.__new__(cls,name, bases, dct) \n", | |
"\n", | |
"class Foo(object,metaclass = FooMetaClass):\n", | |
" a_class_variable = \"a\"\n", | |
" def a_function(self):\n", | |
" print(a_function)\n", | |
" \n", | |
"pp(\"testing out foo\")\n", | |
"pp(\"Foo.my_variable => %r\" % Foo.my_variable)\n", | |
"foo = Foo()\n", | |
"pp(\"foo.my_function() => %r\" % foo.my_function())" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 11, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"def CreateRpcFunction(name):\n", | |
" def wrappedFunction(self,*args,**kwArgs):\n", | |
" self.call(name,*args,**kwArgs)\n", | |
" return name\n", | |
" return wrappedFunction" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 19, | |
"metadata": { | |
"collapsed": false, | |
"scrolled": true | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"'dump rpc functions'\n", | |
"['rpc_get_user', 'rpc_list_users', 'rpc_set_user']\n", | |
"\"called name 'rpc_get_user' args () kwArgs {}\"\n", | |
"\"rpcClient.rpc_get_user() => 'rpc_get_user'\"\n", | |
"\"called name 'rpc_list_users' args () kwArgs {'startsWith': 'Fred'}\"\n", | |
"\"rpcClient.rpc_list_user() => 'rpc_list_users'\"\n" | |
] | |
} | |
], | |
"source": [ | |
"wrapFunctionNames = [\"rpc_list_users\",\"rpc_get_user\",\"rpc_set_user\"]\n", | |
"\n", | |
"class RpcClientMeta(type):\n", | |
" def __new__(cls,name,bases, dct):\n", | |
" for name in wrapFunctionNames :\n", | |
" dct[name] = CreateRpcFunction(name)\n", | |
" return type.__new__(cls,name,bases, dct)\n", | |
" \n", | |
"\n", | |
"class RpcClient(object,metaclass = RpcClientMeta):\n", | |
" \n", | |
" def call(self,name,*args,**kwArgs):\n", | |
" \"\"\"\n", | |
" simulates calling the rpc on the server.\n", | |
" \"\"\"\n", | |
" pp(\"called name %r args %r kwArgs %r\" % (name,args,kwArgs))\n", | |
" return name\n", | |
" \n", | |
"rpcClient = RpcClient()\n", | |
"pp(\"dump rpc functions\")\n", | |
"pp([name for name in dir(rpcClient) if name.startswith(\"rpc_\")])\n", | |
"\n", | |
"pp(\"rpcClient.rpc_get_user() => %r\" % rpcClient.rpc_get_user())\n", | |
"pp(\"rpcClient.rpc_list_user() => %r\" % rpcClient.rpc_list_users(startsWith = \"Fred\"))" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": true | |
}, | |
"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.4.3" | |
} | |
}, | |
"nbformat": 4, | |
"nbformat_minor": 0 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment