{"id":1549,"library":"methodtools","title":"Methodtools","description":"Methodtools extends standard `functools` functionality to class methods, providing decorators like `cached_method`, `lru_method`, `weak_method`, and `locked_method`. It simplifies applying common patterns (caching, locking) directly to instance methods. It is currently at version 0.4.7 and has an active, consistent release cadence.","status":"active","version":"0.4.7","language":"en","source_language":"en","source_url":"https://github.com/youknowone/methodtools","tags":["decorators","caching","methods","functools","memoization"],"install":[{"cmd":"pip install methodtools","lang":"bash","label":"Install stable version"}],"dependencies":[],"imports":[{"symbol":"cached_method","correct":"from methodtools import cached_method"},{"symbol":"lru_method","correct":"from methodtools import lru_method"},{"symbol":"weak_method","correct":"from methodtools import weak_method"},{"symbol":"locked_method","correct":"from methodtools import locked_method"}],"quickstart":{"code":"from methodtools import cached_method\n\nclass MyClass:\n    def __init__(self, value):\n        self._value = value\n        self._compute_count = 0\n\n    @cached_method\n    def compute_something(self):\n        \"\"\"A method that computes something expensive.\"\"\"\n        self._compute_count += 1\n        return self._value * 2\n\nobj = MyClass(10)\nprint(f\"First call: {obj.compute_something()}\")\nprint(f\"Second call (cached): {obj.compute_something()}\")\nprint(f\"Compute count (should be 1): {obj._compute_count}\")\n\nobj2 = MyClass(20)\nprint(f\"First call for obj2: {obj2.compute_something()}\")\nprint(f\"Compute count for obj2 (should be 1): {obj2._compute_count}\")","lang":"python","description":"This example demonstrates how to use `cached_method` to memoize the result of an instance method. Subsequent calls with the same arguments will return the cached result without re-executing the method logic. The cache is managed per instance."},"warnings":[{"fix":"Ensure `methodtools` decorators are applied closer to the method definition: `@property \\n @cached_method \\n def my_method(...)`","message":"When combining `methodtools` decorators with `@property`, `@staticmethod`, or `@classmethod`, the order often matters. Generally, `methodtools` decorators should be applied *before* `@property` (i.e., `methodtools` decorator innermost). Incorrect order can lead to caching the property descriptor itself rather than its computed value.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Avoid passing mutable arguments directly to cached methods, or ensure their contents are not modified after the first call. Alternatively, use tuples for mutable sequences or implement custom hashing logic if necessary.","message":"Like `functools.cache`, `cached_method` relies on argument hashability. If a method takes mutable arguments (e.g., lists, dictionaries) and their *contents* change after the first call, the cached result will be returned, not reflecting the changed input. This can lead to stale data.","severity":"gotcha","affected_versions":"All versions"},{"fix":"To clear a method's cache for a specific instance, use `instance.method_name.__wrapped__.cache_clear()`.","message":"For `cached_method` and `lru_method`, the cache is managed per instance. To manually clear the cache for a specific instance's method, you need to access the underlying wrapped function. Direct attribute deletion won't work.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"last_verified":"2026-04-09T00:00:00.000Z","next_check":"2026-07-08T00:00:00.000Z"}