{ "info": { "author": "Rodney Gomes", "author_email": "rodneygomes@gmail.com", "bugtrack_url": null, "classifiers": [], "description": "Introduction\n------------\n\n[![Build Status](https://travis-ci.org/rlgomes/memoize.png)](https://travis-ci.org/rlgomes/memoize)\n\nUsing memoize\n-------------\n\nFrom wikipedia:\n\n> In computing, memoization is an optimization technique used primarily to speed \n> up computer programs by having function calls avoid repeating the calculation of\n> results for previously processed inputs.\n\nThe memoize library can be used to quickly add the memoization feature to any \nexisting function so that you can cache previously calculated results for the \nsame arguments but don't have to \"clutter\" your function code to add the \nmemoization feature into your function.\n\nThere is a pretty simple implementation of such a decorator in some of python's \ndocumentation but the implementation itself is quite basic and won't handle a \nfew of the use cases resolved with this simple decorator. Here is a list of the \nreasons why I wouldn't use the example \"memoized\" decorator from the python \ndocumentation:\n\n 1. It relies on exceptions being raised for it to decide to cache the current \n results from the function you had decorated. Relying on exceptions to be \n thrown to tests if something is on a cache is a bad design IMHO.\n \n 2. The memoized decorator doesn't handle list types and a few others while\n the memoize decorator can be used on any type that can be converted into \n a string by the str() function.\n \n 3. The memoized decorator also doesn't handle the keyword arguments \n \n 4. The memoize decorator allows you to customize your argument hashing function\n which controls how you match the arguments during the caching of results\n previously calculated. The memoized decorator doesn't have this feature.\n\nThe basic memoize decorator can be used quickly by just placing the \"@memoize\"\ndecorator on the line above the function definition and there is also a \n\"memoize_with\" which allows the user to define the argument to unique string id\ntransformation to be used when identify that the arguments being passed to your\nfunction are indeed the same argument combination that was used a while ago.\n\nLets first show a simple example of a very recursive function you may find a \nlittle familiar:\n\n```python\ndef recursive_function_normal(arg):\n if arg <= 0: return 1\n if arg == 1: return 1\n return recursive_function_normal(arg-1) + recursive_function_normal(arg-2)\n```\n\nNow this function seems innocent enough but if you have a close look at the \nrecursive calls within this function you'll realize its quite a complex sum\nof the previous elements with the value of the current element. Now before \nadding the memoize decorator lets see how well this function scales:\n\n```\nrecursive_function_normal(10) took 0ms\nrecursive_function_normal(20) took 13ms\nrecursive_function_normal(30) took 688ms\nrecursive_function_normal(32) took 1605ms\n```\n\nThat does not look promising at all if we wanted to calculate something like the\nvalue for 100 or 200 it would probably take a few hours. Now with memoization \napplied to this same function, like so:\n\n```python\n@memoize\ndef recursive_function_memoized(arg):\n if arg <= 0: return 1\n if arg == 1: return 1\n return recursive_function_memoized(arg-1) + recursive_function_memoized(arg-2)\n```\n\nHere are the numbers:\n\n```\nrecursive_function_memoized(10) took 0ms\nrecursive_function_memoized(20) took 0ms\nrecursive_function_memoized(30) took 0ms\nrecursive_function_memoized(32) took 0ms\n```\n\nEven from scratch calculation 100 is very fast:\n\n```\nrecursive_function_memoized(100) took 2ms\n```\n\nYou might be scratching your head thinking this is impossible but just remember \nthat after you've calculated the value for 10, 20 and 30 when you issue the \ncall for 100 you only have a few \"new\" values to calculate while all the others\nare pulled straight off the memoization cache.\n\nOf course there are situations where the normal memoize decorator isn't efficient\nenough when handling multiple arguments to your functions and when you have a \ngood grasp on how to uniquely encode the arguments being passed to your function\nin a simple string (ie hash) you can replace the built-in \"hashing\" mechanism \nwith your own custom one by using the \"@memoize_with(hash_args)\" declaration\nand then defining the hash_args with the same signature as the function you're\nattempting to memoize. Here is a small example of how to write your own argument\nhashing function.\n\nInstalling\n----------\n\n```\npython setup.py install\n```\n\nor install directly from github with:\n\n```\npip install -e git+git://github.com/rlgomes/memoize.git#egg=memoize\n```\n\nRunning Built-In Tests\n-----------------------\n\nAfter installing the memoize library you can go to the tests directory and run \nall the tests by executing:\n\n```\ncd tests\npython all_tests.py\n```\n\nLicense\n-------\n\nApache 2.0 License (http://www.apache.org/licenses/LICENSE-2.0.html)", "description_content_type": null, "docs_url": null, "download_url": "UNKNOWN", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "UNKNOWN", "keywords": "memoize,library", "license": "Apache 2.0 License", "maintainer": null, "maintainer_email": null, "name": "memoize-2", "package_url": "https://pypi.org/project/memoize-2/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/memoize-2/", "project_urls": { "Download": "UNKNOWN", "Homepage": "UNKNOWN" }, "release_url": "https://pypi.org/project/memoize-2/0.1.0/", "requires_dist": null, "requires_python": null, "summary": "UNKNOWN", "version": "0.1.0" }, "last_serial": 2047618, "releases": { "0.1.0": [ { "comment_text": "", "digests": { "md5": "571ad31a44ce0ae05bb59cbf15b03d66", "sha256": "f7fa77e7cddf5d86ae055a85f6d7960914e33a474206ec82a2d517182b75d0a1" }, "downloads": -1, "filename": "memoize-2-0.1.0.tar.gz", "has_sig": false, "md5_digest": "571ad31a44ce0ae05bb59cbf15b03d66", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 3710, "upload_time": "2016-04-05T17:12:53", "url": "https://files.pythonhosted.org/packages/f5/76/84aa903e3c4b403c1917256d8918bec306b8f0f826eda4614e4521bcf8fe/memoize-2-0.1.0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "571ad31a44ce0ae05bb59cbf15b03d66", "sha256": "f7fa77e7cddf5d86ae055a85f6d7960914e33a474206ec82a2d517182b75d0a1" }, "downloads": -1, "filename": "memoize-2-0.1.0.tar.gz", "has_sig": false, "md5_digest": "571ad31a44ce0ae05bb59cbf15b03d66", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 3710, "upload_time": "2016-04-05T17:12:53", "url": "https://files.pythonhosted.org/packages/f5/76/84aa903e3c4b403c1917256d8918bec306b8f0f826eda4614e4521bcf8fe/memoize-2-0.1.0.tar.gz" } ] }