{"id":2242,"date":"2025-04-21T19:02:37","date_gmt":"2025-04-21T19:02:37","guid":{"rendered":"https:\/\/www.w3computing.com\/articles\/?p=2242"},"modified":"2025-04-21T19:02:41","modified_gmt":"2025-04-21T19:02:41","slug":"exploring-pythons-new-partial-and-functools-cache_property","status":"publish","type":"post","link":"https:\/\/www.w3computing.com\/articles\/exploring-pythons-new-partial-and-functools-cache_property\/","title":{"rendered":"Exploring Python&#8217;s New partial and functools.cache_property for Efficient Code Design"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Python has always been a language that prioritizes readability and developer happiness. Over the years, its standard library has grown with tools that help developers write more expressive, concise, and efficient code. One such area of the standard library that deserves attention\u2014especially with Python 3.12 and beyond\u2014is the <code>functools<\/code> module.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">You might already know <code>functools.partial<\/code>. It\u2019s been around for a while and allows partial function application\u2014essentially \u201cpre-loading\u201d certain arguments of a function and creating a new callable. But Python 3.12 introduced a new, more flexible version: <code>partial<\/code> as a class. This opens the door to subclassing and some really powerful custom behaviors.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Alongside that, Python has gifted us another gem: <code>functools.cache_property<\/code>. If you\u2019ve ever used <code>@property<\/code> in a class and found yourself wishing it could cache its result automatically\u2014without having to use <code>@functools.lru_cache<\/code> hacks\u2014this is exactly what you were dreaming of.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In this tutorial, we&#8217;ll dig deep into both these tools\u2014step by step\u2014and build up your intuition and your toolbox for writing more efficient, readable, and Pythonic code.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Part 1: Understanding <code>partial<\/code> (the new class-based version)<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Let\u2019s kick things off with a refresher.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">A Quick Refresher on <code>functools.partial<\/code><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The classic <code>partial<\/code> function has been around since Python 2.5. It\u2019s often used to freeze some portion of a function\u2019s arguments and keywords, resulting in a new function.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Here\u2019s a basic example:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\"><span class=\"hljs-keyword\">from<\/span> functools <span class=\"hljs-keyword\">import<\/span> partial\n\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">multiply<\/span><span class=\"hljs-params\">(x, y)<\/span>:<\/span>\n    <span class=\"hljs-keyword\">return<\/span> x * y\n\ndouble = partial(multiply, <span class=\"hljs-number\">2<\/span>)\n\nprint(double(<span class=\"hljs-number\">5<\/span>))  <span class=\"hljs-comment\"># Output: 10<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">This is great for simplifying higher-order functions or preparing pre-filled versions of a function for reuse. But it was limited\u2014<code>partial<\/code> was just a function, not something you could subclass or extend easily.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Enter <code>functools.partial<\/code> as a Class<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">As of Python 3.12, <code>partial<\/code> is now implemented as a <strong>class<\/strong>, not just a function.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">So what does that mean for us?<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>We can subclass it.<\/strong><\/li>\n\n\n\n<li><strong>We can customize its behavior.<\/strong><\/li>\n\n\n\n<li><strong>We can introspect and manipulate it more flexibly.<\/strong><\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">Let\u2019s see how.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">Creating Custom Partial Functions (Subclassing)<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Let\u2019s say you\u2019re working in a large codebase and want to track all the calls made through a certain subset of pre-configured functions\u2014maybe for logging or analytics.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">You can now subclass <code>partial<\/code> like so:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\"><span class=\"hljs-keyword\">from<\/span> functools <span class=\"hljs-keyword\">import<\/span> partial\n\n<span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">LoggingPartial<\/span><span class=\"hljs-params\">(partial)<\/span>:<\/span>\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">__call__<\/span><span class=\"hljs-params\">(self, *args, **kwargs)<\/span>:<\/span>\n        print(<span class=\"hljs-string\">f\"Calling <span class=\"hljs-subst\">{self.func.__name__}<\/span> with <span class=\"hljs-subst\">{args}<\/span> and <span class=\"hljs-subst\">{kwargs}<\/span>\"<\/span>)\n        <span class=\"hljs-keyword\">return<\/span> super().__call__(*args, **kwargs)\n\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">greet<\/span><span class=\"hljs-params\">(greeting, name)<\/span>:<\/span>\n    <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-string\">f\"<span class=\"hljs-subst\">{greeting}<\/span>, <span class=\"hljs-subst\">{name}<\/span>!\"<\/span>\n\nhi = LoggingPartial(greet, <span class=\"hljs-string\">\"Hi\"<\/span>)\nprint(hi(<span class=\"hljs-string\">\"Alice\"<\/span>))  <span class=\"hljs-comment\"># Output includes logging<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">This is powerful. You now have an easy way to inject cross-cutting concerns (like logging, timing, metrics, etc.) into your partials.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Want to track performance? Easy.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\"><span class=\"hljs-keyword\">import<\/span> time\n\n<span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">TimedPartial<\/span><span class=\"hljs-params\">(partial)<\/span>:<\/span>\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">__call__<\/span><span class=\"hljs-params\">(self, *args, **kwargs)<\/span>:<\/span>\n        start = time.perf_counter()\n        result = super().__call__(*args, **kwargs)\n        end = time.perf_counter()\n        print(<span class=\"hljs-string\">f\"<span class=\"hljs-subst\">{self.func.__name__}<\/span> took <span class=\"hljs-subst\">{end - start:<span class=\"hljs-number\">.4<\/span>f}<\/span> seconds\"<\/span>)\n        <span class=\"hljs-keyword\">return<\/span> result<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">This kind of subclassing was not possible before 3.12.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">Exploring Attributes of <code>partial<\/code><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">When you use the new class-based <code>partial<\/code>, you can inspect its arguments and the original function easily:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\">p = partial(multiply, <span class=\"hljs-number\">2<\/span>)\nprint(p.func)       <span class=\"hljs-comment\"># &lt;function multiply&gt;<\/span>\nprint(p.args)       <span class=\"hljs-comment\"># (2,)<\/span>\nprint(p.keywords)   <span class=\"hljs-comment\"># {}<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">This can be especially useful for debugging or building higher-order utilities that inspect and adapt function behavior dynamically.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">Composition with <code>partial<\/code><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Ever needed to create factory-like behavior? Combine <code>partial<\/code> with higher-order functions:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">make_tag<\/span><span class=\"hljs-params\">(tag_name)<\/span>:<\/span>\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">wrapper<\/span><span class=\"hljs-params\">(content)<\/span>:<\/span>\n        <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-string\">f\"&lt;<span class=\"hljs-subst\">{tag_name}<\/span>&gt;<span class=\"hljs-subst\">{content}<\/span>&lt;\/<span class=\"hljs-subst\">{tag_name}<\/span>&gt;\"<\/span>\n    <span class=\"hljs-keyword\">return<\/span> wrapper\n\nbold = partial(make_tag, <span class=\"hljs-string\">\"strong\"<\/span>)\n\nprint(bold()(<span class=\"hljs-string\">\"hello\"<\/span>))  <span class=\"hljs-comment\"># &lt;strong&gt;hello&lt;\/strong&gt;<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">This is elegant and lends itself well to DSLs (Domain Specific Languages), web frameworks, and UI generation.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">Partial in Functional Programming Pipelines<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Let\u2019s take a slightly more complex example\u2014a data transformation pipeline.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\"><span class=\"hljs-keyword\">from<\/span> functools <span class=\"hljs-keyword\">import<\/span> partial\n\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">transform<\/span><span class=\"hljs-params\">(data, multiplier=<span class=\"hljs-number\">1<\/span>, offset=<span class=\"hljs-number\">0<\/span>)<\/span>:<\/span>\n    <span class=\"hljs-keyword\">return<\/span> &#91;x * multiplier + offset <span class=\"hljs-keyword\">for<\/span> x <span class=\"hljs-keyword\">in<\/span> data]\n\n<span class=\"hljs-comment\"># Now build different pipelines<\/span>\ndouble_and_add_1 = partial(transform, multiplier=<span class=\"hljs-number\">2<\/span>, offset=<span class=\"hljs-number\">1<\/span>)\nscale_down = partial(transform, multiplier=<span class=\"hljs-number\">0.5<\/span>)\n\ndata = &#91;<span class=\"hljs-number\">10<\/span>, <span class=\"hljs-number\">20<\/span>, <span class=\"hljs-number\">30<\/span>]\nprint(double_and_add_1(data))  <span class=\"hljs-comment\"># &#91;21, 41, 61]<\/span>\nprint(scale_down(data))       <span class=\"hljs-comment\"># &#91;5.0, 10.0, 15.0]<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">By preconfiguring partials, you can clean up the logic in your code, reduce duplication, and keep your business logic clean.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Part 2: <code>functools.cache_property<\/code> \u2014 Caching Made Beautiful<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">We all love <code>@property<\/code> for its elegant way of encapsulating logic behind attribute-like access. But when the computation is expensive and doesn\u2019t need to be re-run every time, caching becomes necessary.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Historically, this meant using <code>@functools.lru_cache<\/code>, or writing your own boilerplate inside the getter. But no more.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">Introducing <code>@functools.cache_property<\/code><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">As of Python 3.12, we get a beautiful decorator: <code>@cache_property<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Let\u2019s see it in action.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\"><span class=\"hljs-keyword\">from<\/span> functools <span class=\"hljs-keyword\">import<\/span> cache_property\n\n<span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">DataFetcher<\/span>:<\/span>\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">__init__<\/span><span class=\"hljs-params\">(self, source)<\/span>:<\/span>\n        self.source = source\n\n<span class=\"hljs-meta\">    @cache_property<\/span>\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">expensive_computation<\/span><span class=\"hljs-params\">(self)<\/span>:<\/span>\n        print(<span class=\"hljs-string\">\"Running expensive computation...\"<\/span>)\n        <span class=\"hljs-comment\"># Simulate some heavy lifting<\/span>\n        <span class=\"hljs-keyword\">return<\/span> sum(i * i <span class=\"hljs-keyword\">for<\/span> i <span class=\"hljs-keyword\">in<\/span> range(<span class=\"hljs-number\">100000<\/span>))\n\ndf = DataFetcher(<span class=\"hljs-string\">\"db\"<\/span>)\nprint(df.expensive_computation)  <span class=\"hljs-comment\"># Triggers computation<\/span>\nprint(df.expensive_computation)  <span class=\"hljs-comment\"># Cached result, no print<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Boom. No need for custom caching code. It\u2019s like <code>@property<\/code>, but with built-in memory.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">How It Works Behind the Scenes<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><code>cache_property<\/code> is basically a read-only, one-time-computed property.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>It&#8217;s non-overridable: You can&#8217;t assign to it later.<\/li>\n\n\n\n<li>It stores the value in the instance&#8217;s <code>__dict__<\/code> the first time it&#8217;s called.<\/li>\n\n\n\n<li>After that, accessing the property is as fast as a dictionary lookup.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">You can verify that by checking <code>__dict__<\/code>:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\">print(df.__dict__)<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">You\u2019ll see that <code>expensive_computation<\/code> is now just stored like any other attribute.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">Comparison with <code>@cached_property<\/code><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Python 3.8 introduced <code>@functools.cached_property<\/code>. You might be wondering\u2014how is <code>cache_property<\/code> different?<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong><code>cached_property<\/code><\/strong> is writable. You can manually override or delete it.<\/li>\n\n\n\n<li><strong><code>cache_property<\/code><\/strong> is strict: read-only after the first calculation.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">This small difference can be crucial for making sure properties aren\u2019t accidentally mutated in large codebases.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Example:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-9\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\"><span class=\"hljs-keyword\">from<\/span> functools <span class=\"hljs-keyword\">import<\/span> cached_property\n\n<span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">Example<\/span>:<\/span>\n<span class=\"hljs-meta\">    @cached_property<\/span>\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">val<\/span><span class=\"hljs-params\">(self)<\/span>:<\/span>\n        <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-number\">42<\/span>\n\ne = Example()\ne.val = <span class=\"hljs-number\">100<\/span>  <span class=\"hljs-comment\"># Allowed!<\/span>\n\n<span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">Example2<\/span>:<\/span>\n<span class=\"hljs-meta\">    @cache_property<\/span>\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">val<\/span><span class=\"hljs-params\">(self)<\/span>:<\/span>\n        <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-number\">42<\/span>\n\ne2 = Example2()\ne2.val = <span class=\"hljs-number\">100<\/span>  <span class=\"hljs-comment\"># Raises AttributeError<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-9\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">If immutability matters to you, <code>cache_property<\/code> is the way to go.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">Practical Use Cases<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">1. Expensive File Reads<\/h4>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-10\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\"><span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">Config<\/span>:<\/span>\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">__init__<\/span><span class=\"hljs-params\">(self, path)<\/span>:<\/span>\n        self.path = path\n\n<span class=\"hljs-meta\">    @cache_property<\/span>\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">contents<\/span><span class=\"hljs-params\">(self)<\/span>:<\/span>\n        <span class=\"hljs-keyword\">with<\/span> open(self.path, <span class=\"hljs-string\">'r'<\/span>) <span class=\"hljs-keyword\">as<\/span> f:\n            <span class=\"hljs-keyword\">return<\/span> f.read()<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-10\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h4 class=\"wp-block-heading\">2. One-time Data Initialization<\/h4>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-11\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\"><span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">User<\/span>:<\/span>\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">__init__<\/span><span class=\"hljs-params\">(self, user_id)<\/span>:<\/span>\n        self.user_id = user_id\n\n<span class=\"hljs-meta\">    @cache_property<\/span>\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">profile<\/span><span class=\"hljs-params\">(self)<\/span>:<\/span>\n        <span class=\"hljs-keyword\">return<\/span> self._load_profile_from_db()\n\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">_load_profile_from_db<\/span><span class=\"hljs-params\">(self)<\/span>:<\/span>\n        print(<span class=\"hljs-string\">\"Fetching from DB\"<\/span>)\n        <span class=\"hljs-keyword\">return<\/span> {<span class=\"hljs-string\">\"name\"<\/span>: <span class=\"hljs-string\">\"Alice\"<\/span>, <span class=\"hljs-string\">\"age\"<\/span>: <span class=\"hljs-number\">30<\/span>}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-11\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">No more accidentally triggering multiple DB calls just because someone accessed <code>user.profile<\/code> more than once.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">Use with Dataclasses and <code>__post_init__<\/code><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Want to pair <code>cache_property<\/code> with <code>dataclasses<\/code>?<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-12\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\"><span class=\"hljs-keyword\">from<\/span> dataclasses <span class=\"hljs-keyword\">import<\/span> dataclass\n<span class=\"hljs-keyword\">from<\/span> functools <span class=\"hljs-keyword\">import<\/span> cache_property\n\n<span class=\"hljs-meta\">@dataclass<\/span>\n<span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">Inventory<\/span>:<\/span>\n    items: list\n\n<span class=\"hljs-meta\">    @cache_property<\/span>\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">total_value<\/span><span class=\"hljs-params\">(self)<\/span>:<\/span>\n        print(<span class=\"hljs-string\">\"Computing total value...\"<\/span>)\n        <span class=\"hljs-keyword\">return<\/span> sum(item&#91;<span class=\"hljs-string\">\"price\"<\/span>] * item&#91;<span class=\"hljs-string\">\"quantity\"<\/span>] <span class=\"hljs-keyword\">for<\/span> item <span class=\"hljs-keyword\">in<\/span> self.items)<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-12\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">Real-World Strategy: Combining <code>partial<\/code> and <code>cache_property<\/code><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">What happens when you combine both of these tools? Magic.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Imagine this scenario:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>You have an object with a <code>@cache_property<\/code> that computes a value.<\/li>\n\n\n\n<li>You use <code>partial<\/code> to bind various configuration options to a generator of that value.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Here\u2019s a toy version:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-13\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\"><span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">Simulator<\/span>:<\/span>\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">__init__<\/span><span class=\"hljs-params\">(self, factor)<\/span>:<\/span>\n        self.factor = factor\n\n<span class=\"hljs-meta\">    @cache_property<\/span>\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">base_data<\/span><span class=\"hljs-params\">(self)<\/span>:<\/span>\n        print(<span class=\"hljs-string\">\"Generating base data...\"<\/span>)\n        <span class=\"hljs-keyword\">return<\/span> &#91;i * self.factor <span class=\"hljs-keyword\">for<\/span> i <span class=\"hljs-keyword\">in<\/span> range(<span class=\"hljs-number\">1000<\/span>)]\n\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">run<\/span><span class=\"hljs-params\">(self, transform)<\/span>:<\/span>\n        <span class=\"hljs-keyword\">return<\/span> transform(self.base_data)\n\n<span class=\"hljs-keyword\">from<\/span> functools <span class=\"hljs-keyword\">import<\/span> partial\n\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">normalize<\/span><span class=\"hljs-params\">(data, divisor)<\/span>:<\/span>\n    <span class=\"hljs-keyword\">return<\/span> &#91;x \/ divisor <span class=\"hljs-keyword\">for<\/span> x <span class=\"hljs-keyword\">in<\/span> data]\n\nsim = Simulator(<span class=\"hljs-number\">2<\/span>)\nnormalize_half = partial(normalize, divisor=<span class=\"hljs-number\">2<\/span>)\nprint(sim.run(normalize_half))  <span class=\"hljs-comment\"># base_data computed once, reused<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-13\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">You\u2019ve now built a caching pipeline using native tools\u2014minimal boilerplate, maximum readability.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Part 3: Deeper Patterns with <code>partial<\/code> and <code>cache_property<\/code><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Let\u2019s stretch our thinking beyond simple wrappers and into more architectural use cases.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">Pattern 1: Strategy Pattern with <code>partial<\/code><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">You can use <code>partial<\/code> to implement the <strong>strategy pattern<\/strong> in a super clean and declarative way. Imagine you have different pricing strategies:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-14\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">base_price<\/span><span class=\"hljs-params\">(product)<\/span>:<\/span>\n    <span class=\"hljs-keyword\">return<\/span> product&#91;<span class=\"hljs-string\">\"price\"<\/span>]\n\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">discount_price<\/span><span class=\"hljs-params\">(product, discount)<\/span>:<\/span>\n    <span class=\"hljs-keyword\">return<\/span> product&#91;<span class=\"hljs-string\">\"price\"<\/span>] * (<span class=\"hljs-number\">1<\/span> - discount)\n\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">premium_price<\/span><span class=\"hljs-params\">(product, multiplier)<\/span>:<\/span>\n    <span class=\"hljs-keyword\">return<\/span> product&#91;<span class=\"hljs-string\">\"price\"<\/span>] * multiplier\n\n<span class=\"hljs-comment\"># Pre-configured strategies<\/span>\nstandard = base_price\nsummer_sale = partial(discount_price, discount=<span class=\"hljs-number\">0.2<\/span>)\nvip = partial(premium_price, multiplier=<span class=\"hljs-number\">1.5<\/span>)\n\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">calculate_total<\/span><span class=\"hljs-params\">(cart, strategy)<\/span>:<\/span>\n    <span class=\"hljs-keyword\">return<\/span> sum(strategy(item) <span class=\"hljs-keyword\">for<\/span> item <span class=\"hljs-keyword\">in<\/span> cart)\n\ncart = &#91;{<span class=\"hljs-string\">\"price\"<\/span>: <span class=\"hljs-number\">100<\/span>}, {<span class=\"hljs-string\">\"price\"<\/span>: <span class=\"hljs-number\">200<\/span>}]\n\nprint(calculate_total(cart, summer_sale))  <span class=\"hljs-comment\"># Applies discount<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-14\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">This keeps your logic open for extension (add new strategies), but closed for modification. Just pass a different partial, no need to rewrite your function logic.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">Pattern 2: Lazy Initialization with <code>cache_property<\/code><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Suppose you\u2019re loading a large model or dataset. You can make it lazy and one-time with <code>cache_property<\/code>.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-15\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\"><span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">MLModel<\/span>:<\/span>\n<span class=\"hljs-meta\">    @cache_property<\/span>\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">model<\/span><span class=\"hljs-params\">(self)<\/span>:<\/span>\n        print(<span class=\"hljs-string\">\"Loading model...\"<\/span>)\n        <span class=\"hljs-comment\"># Simulate heavy loading<\/span>\n        <span class=\"hljs-keyword\">return<\/span> {<span class=\"hljs-string\">\"model\"<\/span>: <span class=\"hljs-string\">\"Large model object\"<\/span>}\n\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">predict<\/span><span class=\"hljs-params\">(self, x)<\/span>:<\/span>\n        <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-string\">f\"Predicted <span class=\"hljs-subst\">{x}<\/span> using <span class=\"hljs-subst\">{self.model}<\/span>\"<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-15\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">This pattern is especially useful for keeping memory usage in check when working in data pipelines or services with a lot of optional heavy features.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Part 4: Edge Cases and Gotchas<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">You\u2019ve seen how great these tools can be\u2014but let\u2019s talk about a few <strong>caveats<\/strong> that could trip you up.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">1. <code>partial<\/code> Doesn\u2019t Always Preserve Function Signatures<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Here\u2019s a subtle but important detail: a <code>partial<\/code> object doesn\u2019t inherit the full signature of the original function.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-16\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\"><span class=\"hljs-keyword\">from<\/span> functools <span class=\"hljs-keyword\">import<\/span> partial\n\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">greet<\/span><span class=\"hljs-params\">(name, greeting=<span class=\"hljs-string\">\"Hello\"<\/span>)<\/span>:<\/span>\n    <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-string\">f\"<span class=\"hljs-subst\">{greeting}<\/span>, <span class=\"hljs-subst\">{name}<\/span>!\"<\/span>\n\nhello = partial(greet, greeting=<span class=\"hljs-string\">\"Hi\"<\/span>)\nprint(hello(<span class=\"hljs-string\">\"Alice\"<\/span>))  <span class=\"hljs-comment\"># Works<\/span>\n\nhelp(hello)  <span class=\"hljs-comment\"># But won't show nice signature<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-16\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">This makes things a little weird for introspection, help systems, or tools like <code>FastAPI<\/code> that rely on function signatures.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\u2705 <strong>Fix:<\/strong> Use <code>functools.update_wrapper<\/code> or use <code>functools.wraps<\/code> manually if wrapping a function.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">2. <code>cache_property<\/code> is not thread-safe (by design)<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">In multi-threaded environments (like web servers), simultaneous first access to a <code>cache_property<\/code> could result in the property being computed multiple times. Example:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-17\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\"><span class=\"hljs-comment\"># Thread 1 and Thread 2 both hit this at the same time<\/span>\n<span class=\"hljs-meta\">@property<\/span>\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">computed_value<\/span><span class=\"hljs-params\">(self)<\/span>:<\/span>\n    print(<span class=\"hljs-string\">\"Heavy computation happening twice!\"<\/span>)\n    ...<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-17\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">\u2705 <strong>Fix:<\/strong> Use locks or other thread-safe patterns if needed.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">3. Be Careful With Side Effects in Cached Properties<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Because <code>cache_property<\/code> runs <strong>once<\/strong>, any side effects you include (like logging, analytics, or resource access) will only happen on the first call. That might surprise you if you forget.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">4. <code>partial<\/code> and Mutable Defaults<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">This old Python gotcha still applies:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-18\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">def add_to_list(value, target=&#91;]):\n    target.append(value)\n    <span class=\"hljs-keyword\">return<\/span> target\n\nbad_partial = partial(add_to_list, <span class=\"hljs-number\">10<\/span>)\n<span class=\"hljs-keyword\">print<\/span>(bad_partial())  <span class=\"hljs-comment\"># &#91;10]<\/span>\n<span class=\"hljs-keyword\">print<\/span>(bad_partial())  <span class=\"hljs-comment\"># &#91;10, 10]<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-18\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">\u2705 <strong>Fix:<\/strong> Avoid mutable defaults like the plague. You already knew that, but it\u2019s worth a reminder.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Part 5: Testing Strategies<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">You\u2019re probably thinking: <em>\u201cOkay, I love these tools, but how do I test them properly?\u201d<\/em><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Let\u2019s look at testing best practices for both.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">Testing <code>partial<\/code> Functions<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">A partial is just a callable, so you can test it directly.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-19\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\"><span class=\"hljs-keyword\">from<\/span> functools <span class=\"hljs-keyword\">import<\/span> partial\n\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">multiply<\/span><span class=\"hljs-params\">(x, y)<\/span>:<\/span>\n    <span class=\"hljs-keyword\">return<\/span> x * y\n\ndouble = partial(multiply, <span class=\"hljs-number\">2<\/span>)\n\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">test_double<\/span><span class=\"hljs-params\">()<\/span>:<\/span>\n    <span class=\"hljs-keyword\">assert<\/span> double(<span class=\"hljs-number\">3<\/span>) == <span class=\"hljs-number\">6<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-19\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">But what if you subclassed <code>partial<\/code>?<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Then you may want to test internal attributes:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-20\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\"><span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">LoggingPartial<\/span><span class=\"hljs-params\">(partial)<\/span>:<\/span>\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">__call__<\/span><span class=\"hljs-params\">(self, *args, **kwargs)<\/span>:<\/span>\n        print(<span class=\"hljs-string\">f\"Calling <span class=\"hljs-subst\">{self.func.__name__}<\/span> with <span class=\"hljs-subst\">{args}<\/span> and <span class=\"hljs-subst\">{kwargs}<\/span>\"<\/span>)\n        <span class=\"hljs-keyword\">return<\/span> super().__call__(*args, **kwargs)\n\np = LoggingPartial(multiply, <span class=\"hljs-number\">3<\/span>)\n\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">test_logging_partial<\/span><span class=\"hljs-params\">()<\/span>:<\/span>\n    <span class=\"hljs-keyword\">assert<\/span> p.func == multiply\n    <span class=\"hljs-keyword\">assert<\/span> p.args == (<span class=\"hljs-number\">3<\/span>,)\n    <span class=\"hljs-keyword\">assert<\/span> p(<span class=\"hljs-number\">4<\/span>) == <span class=\"hljs-number\">12<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-20\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">Testing <code>cache_property<\/code><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">You want to test both:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>The <strong>correctness<\/strong> of the computed result<\/li>\n\n\n\n<li>That it <strong>only computes once<\/strong><\/li>\n<\/ol>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-21\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\"><span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">Demo<\/span>:<\/span>\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">__init__<\/span><span class=\"hljs-params\">(self)<\/span>:<\/span>\n        self.counter = <span class=\"hljs-number\">0<\/span>\n\n<span class=\"hljs-meta\">    @cache_property<\/span>\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">cached<\/span><span class=\"hljs-params\">(self)<\/span>:<\/span>\n        self.counter += <span class=\"hljs-number\">1<\/span>\n        <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-number\">42<\/span>\n\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">test_cached_property<\/span><span class=\"hljs-params\">()<\/span>:<\/span>\n    d = Demo()\n    <span class=\"hljs-keyword\">assert<\/span> d.cached == <span class=\"hljs-number\">42<\/span>\n    <span class=\"hljs-keyword\">assert<\/span> d.cached == <span class=\"hljs-number\">42<\/span>\n    <span class=\"hljs-keyword\">assert<\/span> d.counter == <span class=\"hljs-number\">1<\/span>  <span class=\"hljs-comment\"># Confirm it only ran once<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-21\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">This is an excellent pattern for when you\u2019re dealing with resource-heavy setups and want to be confident about memory and performance.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Part 6: Using These Tools in FastAPI<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Use Case: Dependency Injection with <code>partial<\/code><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">FastAPI relies heavily on <strong>dependency injection<\/strong>, and <code>partial<\/code> is a great tool for injecting preconfigured behavior.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-22\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\"><span class=\"hljs-keyword\">from<\/span> functools <span class=\"hljs-keyword\">import<\/span> partial\n<span class=\"hljs-keyword\">from<\/span> fastapi <span class=\"hljs-keyword\">import<\/span> Depends, FastAPI\n\napp = FastAPI()\n\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">get_user_service<\/span><span class=\"hljs-params\">(prefix: str)<\/span>:<\/span>\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">_get_user_service<\/span><span class=\"hljs-params\">()<\/span>:<\/span>\n        <span class=\"hljs-keyword\">return<\/span> {<span class=\"hljs-string\">\"prefix\"<\/span>: prefix}\n    <span class=\"hljs-keyword\">return<\/span> _get_user_service\n\nuser_service_prod = partial(get_user_service, prefix=<span class=\"hljs-string\">\"prod\"<\/span>)\nuser_service_dev = partial(get_user_service, prefix=<span class=\"hljs-string\">\"dev\"<\/span>)\n\n<span class=\"hljs-meta\">@app.get(\"\/users\")<\/span>\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">read_users<\/span><span class=\"hljs-params\">(service=Depends<span class=\"hljs-params\">(user_service_prod<span class=\"hljs-params\">()<\/span>)<\/span>)<\/span>:<\/span>\n    <span class=\"hljs-keyword\">return<\/span> {<span class=\"hljs-string\">\"service\"<\/span>: service}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-22\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">This makes it super clean to switch environments, without rewriting dependencies.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">Use Case: Lazy Loading in FastAPI with <code>cache_property<\/code><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">For example, lazy loading a machine learning model:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-23\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\"><span class=\"hljs-keyword\">from<\/span> fastapi <span class=\"hljs-keyword\">import<\/span> FastAPI\n\napp = FastAPI()\n\n<span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">Predictor<\/span>:<\/span>\n<span class=\"hljs-meta\">    @cache_property<\/span>\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">model<\/span><span class=\"hljs-params\">(self)<\/span>:<\/span>\n        print(<span class=\"hljs-string\">\"Loading model...\"<\/span>)\n        <span class=\"hljs-keyword\">return<\/span> {<span class=\"hljs-string\">\"loaded_model\"<\/span>: <span class=\"hljs-literal\">True<\/span>}\n\npredictor = Predictor()\n\n<span class=\"hljs-meta\">@app.get(\"\/predict\")<\/span>\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">predict<\/span><span class=\"hljs-params\">()<\/span>:<\/span>\n    model = predictor.model\n    <span class=\"hljs-keyword\">return<\/span> {<span class=\"hljs-string\">\"status\"<\/span>: <span class=\"hljs-string\">\"ok\"<\/span>}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-23\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Even under load, <code>model<\/code> is only initialized once.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Part 7: Using These Tools in Django<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">In Django, <code>cache_property<\/code> can be used to improve ORM access efficiency, and <code>partial<\/code> is great for forms, views, or signal configuration.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\"><code>cache_property<\/code> in Django Models or Views<\/h3>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-24\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\"><span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">MyView<\/span><span class=\"hljs-params\">(View)<\/span>:<\/span>\n<span class=\"hljs-meta\">    @cache_property<\/span>\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">expensive_lookup<\/span><span class=\"hljs-params\">(self)<\/span>:<\/span>\n        <span class=\"hljs-keyword\">return<\/span> SomeModel.objects.select_related(<span class=\"hljs-string\">\"something\"<\/span>).get(id=self.kwargs&#91;<span class=\"hljs-string\">\"id\"<\/span>])\n\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">get<\/span><span class=\"hljs-params\">(self, request, *args, **kwargs)<\/span>:<\/span>\n        data = self.expensive_lookup  <span class=\"hljs-comment\"># Only queried once<\/span>\n        <span class=\"hljs-keyword\">return<\/span> JsonResponse({<span class=\"hljs-string\">\"name\"<\/span>: data.name})<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-24\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">This avoids hitting the database multiple times in a single request.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\"><code>partial<\/code> in Django Form Factories<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Want to preconfigure certain fields dynamically?<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-25\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">make_custom_form<\/span><span class=\"hljs-params\">(label_text)<\/span>:<\/span>\n    <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">CustomForm<\/span><span class=\"hljs-params\">(forms.Form)<\/span>:<\/span>\n        name = forms.CharField(label=label_text)\n    <span class=\"hljs-keyword\">return<\/span> CustomForm\n\nShortForm = partial(make_custom_form, label_text=<span class=\"hljs-string\">\"Short Name\"<\/span>)\nLongForm = partial(make_custom_form, label_text=<span class=\"hljs-string\">\"Full Legal Name\"<\/span>)<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-25\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Now you have customizable forms without repeating yourself.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\"><code>partial<\/code> for Signal Handlers<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Need signal handlers with custom behavior?<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-26\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\"><span class=\"hljs-keyword\">from<\/span> django.db.models.signals <span class=\"hljs-keyword\">import<\/span> post_save\n\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">notify_user<\/span><span class=\"hljs-params\">(action, instance, **kwargs)<\/span>:<\/span>\n    print(<span class=\"hljs-string\">f\"<span class=\"hljs-subst\">{action}<\/span> -&gt; <span class=\"hljs-subst\">{instance}<\/span>\"<\/span>)\n\nnotify_created = partial(notify_user, <span class=\"hljs-string\">\"created\"<\/span>)\npost_save.connect(notify_created, sender=MyModel)<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-26\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Final Thoughts<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">With the upgrades in Python 3.12, <code>functools.partial<\/code> becomes subclassable, inspectable, and customizable\u2014meaning it\u2019s not just a shortcut anymore, it\u2019s a real design tool. And <code>cache_property<\/code> offers a long-awaited, elegant solution to a common performance issue without hacks or third-party packages.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">These aren\u2019t flashy features\u2014but they\u2019re <strong>quietly powerful<\/strong>. They let you build <strong>faster<\/strong>, more <strong>expressive<\/strong>, and <strong>bug-resistant<\/strong> systems, whether you\u2019re prototyping or scaling production services.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If you&#8217;re designing APIs, building ML pipelines, crunching data, or wrangling legacy codebases\u2014these tools will make your life easier.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Python has always been a language that prioritizes readability and developer happiness. Over the years, its standard library has grown with tools that help developers write more expressive, concise, and efficient code. One such area of the standard library that deserves attention\u2014especially with Python 3.12 and beyond\u2014is the functools module. You might already know functools.partial. [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_genesis_hide_title":false,"_genesis_hide_breadcrumbs":false,"_genesis_hide_singular_image":false,"_genesis_hide_footer_widgets":false,"_genesis_custom_body_class":"","_genesis_custom_post_class":"","_genesis_layout":"","_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[4,6],"tags":[],"class_list":["post-2242","post","type-post","status-publish","format-standard","category-programming-languages","category-python","entry"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.6 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Exploring Python&#039;s New partial and functools.cache_property<\/title>\n<meta name=\"description\" content=\"A comprehensive Python tutorial on partial and cache_property. Perfect for developers looking to modernize their code and apply advanced patterns in real-world applications.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.w3computing.com\/articles\/exploring-pythons-new-partial-and-functools-cache_property\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Exploring Python&#039;s New partial and functools.cache_property\" \/>\n<meta property=\"og:description\" content=\"A comprehensive Python tutorial on partial and cache_property. Perfect for developers looking to modernize their code and apply advanced patterns in real-world applications.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.w3computing.com\/articles\/exploring-pythons-new-partial-and-functools-cache_property\/\" \/>\n<meta property=\"article:published_time\" content=\"2025-04-21T19:02:37+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-04-21T19:02:41+00:00\" \/>\n<meta name=\"author\" content=\"w3compadmin\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"w3compadmin\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"6 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"TechArticle\",\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/exploring-pythons-new-partial-and-functools-cache_property\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/exploring-pythons-new-partial-and-functools-cache_property\\\/\"},\"author\":{\"name\":\"w3compadmin\",\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/#\\\/schema\\\/person\\\/a550b3e20d78bb4f79b7c6b7b53f0561\"},\"headline\":\"Exploring Python&#8217;s New partial and functools.cache_property for Efficient Code Design\",\"datePublished\":\"2025-04-21T19:02:37+00:00\",\"dateModified\":\"2025-04-21T19:02:41+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/exploring-pythons-new-partial-and-functools-cache_property\\\/\"},\"wordCount\":1383,\"articleSection\":[\"Programming Languages\",\"Python\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/exploring-pythons-new-partial-and-functools-cache_property\\\/\",\"url\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/exploring-pythons-new-partial-and-functools-cache_property\\\/\",\"name\":\"Exploring Python's New partial and functools.cache_property\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/#website\"},\"datePublished\":\"2025-04-21T19:02:37+00:00\",\"dateModified\":\"2025-04-21T19:02:41+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/#\\\/schema\\\/person\\\/a550b3e20d78bb4f79b7c6b7b53f0561\"},\"description\":\"A comprehensive Python tutorial on partial and cache_property. Perfect for developers looking to modernize their code and apply advanced patterns in real-world applications.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/exploring-pythons-new-partial-and-functools-cache_property\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/exploring-pythons-new-partial-and-functools-cache_property\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/exploring-pythons-new-partial-and-functools-cache_property\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Articles Home\",\"item\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Programming Languages\",\"item\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/programming-languages\\\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Exploring Python&#8217;s New partial and functools.cache_property for Efficient Code Design\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/#website\",\"url\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/\",\"name\":\"Developer Articles Hub\",\"description\":\"\",\"alternateName\":\"Developer Articles\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/#\\\/schema\\\/person\\\/a550b3e20d78bb4f79b7c6b7b53f0561\",\"name\":\"w3compadmin\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/wp-content\\\/litespeed\\\/avatar\\\/bd481d404e42caa2763662a3bfe825f8.jpg?ver=1780141266\",\"url\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/wp-content\\\/litespeed\\\/avatar\\\/bd481d404e42caa2763662a3bfe825f8.jpg?ver=1780141266\",\"contentUrl\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/wp-content\\\/litespeed\\\/avatar\\\/bd481d404e42caa2763662a3bfe825f8.jpg?ver=1780141266\",\"caption\":\"w3compadmin\"},\"sameAs\":[\"http:\\\/\\\/w3computing.com\\\/articles\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Exploring Python's New partial and functools.cache_property","description":"A comprehensive Python tutorial on partial and cache_property. Perfect for developers looking to modernize their code and apply advanced patterns in real-world applications.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.w3computing.com\/articles\/exploring-pythons-new-partial-and-functools-cache_property\/","og_locale":"en_US","og_type":"article","og_title":"Exploring Python's New partial and functools.cache_property","og_description":"A comprehensive Python tutorial on partial and cache_property. Perfect for developers looking to modernize their code and apply advanced patterns in real-world applications.","og_url":"https:\/\/www.w3computing.com\/articles\/exploring-pythons-new-partial-and-functools-cache_property\/","article_published_time":"2025-04-21T19:02:37+00:00","article_modified_time":"2025-04-21T19:02:41+00:00","author":"w3compadmin","twitter_card":"summary_large_image","twitter_misc":{"Written by":"w3compadmin","Est. reading time":"6 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"TechArticle","@id":"https:\/\/www.w3computing.com\/articles\/exploring-pythons-new-partial-and-functools-cache_property\/#article","isPartOf":{"@id":"https:\/\/www.w3computing.com\/articles\/exploring-pythons-new-partial-and-functools-cache_property\/"},"author":{"name":"w3compadmin","@id":"https:\/\/www.w3computing.com\/articles\/#\/schema\/person\/a550b3e20d78bb4f79b7c6b7b53f0561"},"headline":"Exploring Python&#8217;s New partial and functools.cache_property for Efficient Code Design","datePublished":"2025-04-21T19:02:37+00:00","dateModified":"2025-04-21T19:02:41+00:00","mainEntityOfPage":{"@id":"https:\/\/www.w3computing.com\/articles\/exploring-pythons-new-partial-and-functools-cache_property\/"},"wordCount":1383,"articleSection":["Programming Languages","Python"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/www.w3computing.com\/articles\/exploring-pythons-new-partial-and-functools-cache_property\/","url":"https:\/\/www.w3computing.com\/articles\/exploring-pythons-new-partial-and-functools-cache_property\/","name":"Exploring Python's New partial and functools.cache_property","isPartOf":{"@id":"https:\/\/www.w3computing.com\/articles\/#website"},"datePublished":"2025-04-21T19:02:37+00:00","dateModified":"2025-04-21T19:02:41+00:00","author":{"@id":"https:\/\/www.w3computing.com\/articles\/#\/schema\/person\/a550b3e20d78bb4f79b7c6b7b53f0561"},"description":"A comprehensive Python tutorial on partial and cache_property. Perfect for developers looking to modernize their code and apply advanced patterns in real-world applications.","breadcrumb":{"@id":"https:\/\/www.w3computing.com\/articles\/exploring-pythons-new-partial-and-functools-cache_property\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.w3computing.com\/articles\/exploring-pythons-new-partial-and-functools-cache_property\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.w3computing.com\/articles\/exploring-pythons-new-partial-and-functools-cache_property\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Articles Home","item":"https:\/\/www.w3computing.com\/articles\/"},{"@type":"ListItem","position":2,"name":"Programming Languages","item":"https:\/\/www.w3computing.com\/articles\/programming-languages\/"},{"@type":"ListItem","position":3,"name":"Exploring Python&#8217;s New partial and functools.cache_property for Efficient Code Design"}]},{"@type":"WebSite","@id":"https:\/\/www.w3computing.com\/articles\/#website","url":"https:\/\/www.w3computing.com\/articles\/","name":"Developer Articles Hub","description":"","alternateName":"Developer Articles","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.w3computing.com\/articles\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/www.w3computing.com\/articles\/#\/schema\/person\/a550b3e20d78bb4f79b7c6b7b53f0561","name":"w3compadmin","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.w3computing.com\/articles\/wp-content\/litespeed\/avatar\/bd481d404e42caa2763662a3bfe825f8.jpg?ver=1780141266","url":"https:\/\/www.w3computing.com\/articles\/wp-content\/litespeed\/avatar\/bd481d404e42caa2763662a3bfe825f8.jpg?ver=1780141266","contentUrl":"https:\/\/www.w3computing.com\/articles\/wp-content\/litespeed\/avatar\/bd481d404e42caa2763662a3bfe825f8.jpg?ver=1780141266","caption":"w3compadmin"},"sameAs":["http:\/\/w3computing.com\/articles"]}]}},"featured_image_src":null,"featured_image_src_square":null,"author_info":{"display_name":"w3compadmin","author_link":"https:\/\/www.w3computing.com\/articles\/author\/w3compadmin\/"},"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.w3computing.com\/articles\/wp-json\/wp\/v2\/posts\/2242","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.w3computing.com\/articles\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.w3computing.com\/articles\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.w3computing.com\/articles\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.w3computing.com\/articles\/wp-json\/wp\/v2\/comments?post=2242"}],"version-history":[{"count":2,"href":"https:\/\/www.w3computing.com\/articles\/wp-json\/wp\/v2\/posts\/2242\/revisions"}],"predecessor-version":[{"id":2244,"href":"https:\/\/www.w3computing.com\/articles\/wp-json\/wp\/v2\/posts\/2242\/revisions\/2244"}],"wp:attachment":[{"href":"https:\/\/www.w3computing.com\/articles\/wp-json\/wp\/v2\/media?parent=2242"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.w3computing.com\/articles\/wp-json\/wp\/v2\/categories?post=2242"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.w3computing.com\/articles\/wp-json\/wp\/v2\/tags?post=2242"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}