Contents:
(This section is still incomplete.)
These are topical guides about the various modules in the Python Toolbox.
It focuses on giving the motivation for each module in the Python Toolbox, explaining what it’s good for and the basics of using it.
abc_tools
- documentation not written¶address_tools
- documentation not written¶arguments_profile
- documentation not written¶binary_search
- documentation not written¶caching
¶The caching
modules provides tools related to caching:
caching.cache()
¶The idea of a caching decorator is very cool. You decorate your function with a caching decorator:
>>> from python_toolbox import caching
>>>
>>> @caching.cache
... def f(x):
... print('Calculating...')
... return x ** x # Some long expensive computation
And then, every time you call it, it’ll cache the results for next time:
>>> f(4)
Calculating...
256
>>> f(5)
Calculating...
3125
>>> f(5)
3125
>>> f(5)
3125
As you can see, after the first time we calculate f(5)
the result gets
saved to a cache and every time we’ll call f(5)
Python will return the
result from the cache instead of calculating it again. This prevents making
redundant performance-expensive calculations.
Now, depending on the function, there can be many different ways to make the same call. For example, if you have a function defined like this:
def g(a, b=2, **kwargs):
return whatever
Then g(1)
, g(1, 2)
, g(b=2, a=1)
and even g(1, 2, **{})
are all equivalent. They give the exact same arguments, just in different ways. Most caching decorators out there don’t understand that. If you call g(1)
and then g(1, 2)
, they will calculate the function again, because they don’t understand that it’s exactly the same call and they could use the cached result.
Enter caching.cache()
:
>>> @caching.cache()
... def g(a, b=2, **kwargs):
... print('Calculating')
... return (a, b, kwargs)
...
>>> g(1)
Calculating
(1, 2, {})
>>> g(1, 2) # Look ma, no calculating:
(1, 2, {})
>>> g(b=2, a=1) # No calculating again:
(1, 2, {})
>>> g(1, 2, **{}) # No calculating here either:
(1, 2, {})
>>> g('something_else') # Now calculating for different arguments:
Calculating
('something_else', 2, {})
As you can see above, caching.cache()
analyzes the function and understands
that calls like g(1)
and g(1, 2)
are identical and therefore should be
cached together.
By default, the cache size will be unlimited. If you want to limit the cache size, pass in the max_size
argument:
>>> @caching.cache(max_size=7)
... def f(): pass
If and when the cache size reaches the limit (7 in this case), old values will get thrown away according to a LRU order.
caching.cache()
arguments with sleekrefs. Sleekrefs are a more robust variation of weakrefs. They are basically a gracefully-degrading version of weakrefs, so you can use them on un-weakreff-able objects like int
, and they will just use regular references.
The usage of sleekrefs prevents memory leaks when using potentially-heavy arguments.
caching.CachedType
¶Sometimes you define classes whose instances hold absolutely no state on them,
and are completey determined by the arguments passed to them. In these cases
using caching.CachedType
as a metaclass would cache class instances,
preventing more than one of them from being created:
>>> from python_toolbox import caching
>>>
>>> class A(object):
... __metaclass__ = caching.CachedType
... def __init__(self, a=1, b=2):
... self.a = a
... self.b = b
Now every time you create an instance, it’ll be cached:
>>> my_instance = A(b=3)
And the next time you’ll create an instance with the same arguments:
>>> another_instance = A(b=3)
No instance will be actually created; the same instance from before will be used:
>>> assert another_instance is my_instance
caching.CachedProperty
¶Oftentimes you have a property
on a class that never gets changed and
needs to be calculated only once. This is a good situation to use
caching.CachedProperty
in order to have that property be calculated
only one time per instance. Any future accesses to the property will use the
cached value.
Example:
>>> import time
>>> from python_toolbox import caching
>>>
>>> class MyObject(object):
... # ... Regular definitions here
... def _get_personality(self):
... print('Calculating personality...')
... time.sleep(5) # Time consuming process...
... return 'Nice person'
... personality = caching.CachedProperty(_get_personality)
Now we create an object and calculate its “personality”:
>>> my_object = MyObject()
>>> my_object.personality
'Nice person'
>>> # We had to wait 5 seconds for the calculation!
Consecutive calls will be instantaneous:
>>> my_object.personality
'Nice person'
>>> # That one was cached and therefore instantaneous!
change_tracker
- documentation not written¶cheat_hashing
- documentation not written¶color_tools
- documentation not written¶comparison_tools
- documentation not written¶context_managers
- documentation not written¶copy_mode
- documentation not written¶copy_tools
- documentation not written¶cute_inspect
- documentation not written¶cute_iter_tools
- documentation not written¶cute_profile
- documentation not written¶cute_testing
- documentation not written¶decorator_tools
- documentation not written¶dict_tools
- documentation not written¶emitters
- documentation not written¶exceptions
- documentation not written¶freezers
- documentation not written¶function_anchoring_type
- documentation not written¶gc_tools
- documentation not written¶identities
- documentation not written¶import_tools
- documentation not written¶infinity
- documentation not written¶introspection_tools
- documentation not written¶logic_tools
- documentation not written¶math_tools
- documentation not written¶misc_tools
- documentation not written¶module_tasting
- documentation not written¶monkeypatch_copy_reg
- documentation not written¶monkeypatching_tools
- documentation not written¶nifty_collections
- documentation not written¶os_tools
- documentation not written¶package_finder
- documentation not written¶path_tools
- documentation not written¶persistent
- documentation not written¶pickle_tools
- documentation not written¶process_priority
- documentation not written¶proxy_property
- documentation not written¶queue_tools
- documentation not written¶random_tools
- documentation not written¶re_tools
- documentation not written¶read_write_lock
- documentation not written¶reasoned_bool
- documentation not written¶rst_tools
- documentation not written¶sequence_tools
- documentation not written¶sleek_refs
- documentation not written¶string_cataloging
- documentation not written¶string_tools
- documentation not written¶sys_tools
- documentation not written¶temp_file_tools
- documentation not written¶temp_value_setters
- documentation not written¶third_party
- documentation not written¶tracing_tools
- documentation not written¶version_info
- documentation not written¶wx_tools
- documentation not written¶zip_tools
- documentation not written¶There are three Python Toolbox groups, a.k.a. mailing lists:
This documentation is still incomplete. If you have any questions or feedback, say hello on the mailing list!
The Python Toolbox repository is at: https://github.com/cool-RR/python_toolbox
Feel free to fork and send pull requests!