Created
February 5, 2015 17:36
-
-
Save aericson/0a456a725d1f16ad1146 to your computer and use it in GitHub Desktop.
Exemplo de uso de metaclass
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
{ | |
"metadata": { | |
"name": "", | |
"signature": "sha256:ae2acf626e9dee6ea411b000dd488b72ceb7f7f0c5f76c6372d11a497de63669" | |
}, | |
"nbformat": 3, | |
"nbformat_minor": 0, | |
"worksheets": [ | |
{ | |
"cells": [ | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"O que a gente quer \u00e9 ter um `__doc__` gerado automaticamente" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"A implementa\u00e7\u00e3o mais simples seria:" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"class A(object):\n", | |
" \n", | |
" def __init__(self, resource=None):\n", | |
" self.resource = resource\n", | |
" \n", | |
" def _get_doc(self):\n", | |
" return self.resource\n", | |
"\n", | |
" __doc__ = property(_get_doc)" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [], | |
"prompt_number": 1 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"a = A(resource='doc of method x in api')" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [], | |
"prompt_number": 2 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"a.__doc__" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"metadata": {}, | |
"output_type": "pyout", | |
"prompt_number": 3, | |
"text": [ | |
"'doc of method x in api'" | |
] | |
} | |
], | |
"prompt_number": 3 | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Mas e se A n\u00e3o tiver self.resource?" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"a = A()\n", | |
"print a.__doc__" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"None\n" | |
] | |
} | |
], | |
"prompt_number": 4 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"class A(object):\n", | |
" \n", | |
" def __init__(self, resource=None):\n", | |
" self.resource = resource\n", | |
" \n", | |
" def _get_doc(self):\n", | |
" if self.resource:\n", | |
" return self.resource\n", | |
" else:\n", | |
" return ''\n", | |
" __doc__ = property(_get_doc)" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [], | |
"prompt_number": 5 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"a = A()\n", | |
"print a.__doc__" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"\n" | |
] | |
} | |
], | |
"prompt_number": 6 | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Seria legal se `__doc__` tivesse alguma coisa interessante caso n\u00e3o tivesse resource.\n", | |
"Seria bom se ele retornasse a `__doc__` da class que \u00e9 o comportamento padr\u00e3o do `__doc__`" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"class A(object):\n", | |
" \"\"\"This is a doc string\"\"\"" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [], | |
"prompt_number": 7 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"a = A()\n", | |
"a.__doc__" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"metadata": {}, | |
"output_type": "pyout", | |
"prompt_number": 8, | |
"text": [ | |
"'This is a doc string'" | |
] | |
} | |
], | |
"prompt_number": 8 | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Seguindo nossa implementa\u00e7\u00e3o anterior:" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"class A(object):\n", | |
" \"\"\"This is a docstring\"\"\"\n", | |
" \n", | |
" def __init__(self, resource=None):\n", | |
" self.resource = resource\n", | |
" \n", | |
" def _get_doc(self):\n", | |
" if self.resource:\n", | |
" return self.resource\n", | |
" else:\n", | |
" return A.__doc__\n", | |
"\n", | |
" __doc__ = property(_get_doc)" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [], | |
"prompt_number": 9 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"a = A()\n", | |
"print a.__doc__" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"<property object at 0x7f2a8cb9cfc8>\n" | |
] | |
} | |
], | |
"prompt_number": 10 | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"O problema \u00e9 que quando criamos a property pra `__doc__` o docstring original se perde.\n", | |
"A \u00fanica solu\u00e7\u00e3o que encontrei foi guardar o conteudo da docstring no momento de cria\u00e7\u00e3o da class." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"class KeepDocMetaClass(type):\n", | |
"\n", | |
" def __new__(cls, name, bases, attrs):\n", | |
" def _get_doc(self):\n", | |
" if self.resource:\n", | |
" return self.resource\n", | |
" # attrs['__doc__'] vai ter o valor da docstring\n", | |
" return attrs.get('__doc__')\n", | |
" new_attrs = attrs.copy()\n", | |
" new_attrs['__doc__'] = property(_get_doc)\n", | |
"\n", | |
" return super(KeepDocMetaClass, cls).__new__(cls, name, bases, new_attrs)\n", | |
"\n", | |
"\n", | |
"class SimpleTapiocaClient(object):\n", | |
" \"\"\"This has a doc string and will make sphinx happy :)\"\"\"\n", | |
" __metaclass__ = KeepDocMetaClass\n", | |
" \n", | |
" def __init__(self, resource=None):\n", | |
" self.resource = resource" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [], | |
"prompt_number": 11 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"a = SimpleTapiocaClient(resource='a new docstring!')\n", | |
"a.__doc__" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"metadata": {}, | |
"output_type": "pyout", | |
"prompt_number": 12, | |
"text": [ | |
"'a new docstring!'" | |
] | |
} | |
], | |
"prompt_number": 12 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"a = SimpleTapiocaClient()\n", | |
"a.__doc__" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"metadata": {}, | |
"output_type": "pyout", | |
"prompt_number": 13, | |
"text": [ | |
"'This has a doc string and will make sphinx happy :)'" | |
] | |
} | |
], | |
"prompt_number": 13 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [], | |
"prompt_number": 13 | |
} | |
], | |
"metadata": {} | |
} | |
] | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment