Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p><strong>partials</strong> are incredibly useful.</p> <p>For instance, in a 'pipe-lined' sequence of function calls (in which the returned value from one function is the argument passed to the next).</p> <p>Sometimes a function in such a pipeline requires a <em>single argument</em>, but the function immediately upstream from it returns <em>two values</em>.</p> <p>In this scenario, <code>functools.partial</code> might allow you to keep this function pipeline intact.</p> <p>Here's a specific, isolated example: suppose you want to sort some data by each data point's distance from some target:</p> <pre><code># create some data import random as RND fnx = lambda: RND.randint(0, 10) data = [ (fnx(), fnx()) for c in range(10) ] target = (2, 4) import math def euclid_dist(v1, v2): x1, y1 = v1 x2, y2 = v2 return math.sqrt((x2 - x1)**2 + (y2 - y1)**2) </code></pre> <p>To sort this data by distance from the target, what you would like to do of course is this:</p> <pre><code>data.sort(key=euclid_dist) </code></pre> <p>but you can't--the <em>sort</em> method's <em>key</em> parameter only accepts functions that take a <em>single</em> argument.</p> <p>so re-write <code>euclid_dist</code> as a function taking a <em>single</em> parameter:</p> <pre><code>from functools import partial p_euclid_dist = partial(euclid_dist, target) </code></pre> <p><code>p_euclid_dist</code> now accepts a single argument, </p> <pre><code>&gt;&gt;&gt; p_euclid_dist((3, 3)) 1.4142135623730951 </code></pre> <p>so now you can sort your data by passing in the partial function for the sort method's key argument:</p> <pre><code>data.sort(key=p_euclid_dist) # verify that it works: for p in data: print(round(p_euclid_dist(p), 3)) 1.0 2.236 2.236 3.606 4.243 5.0 5.831 6.325 7.071 8.602 </code></pre> <p>Or for instance, one of the function's arguments changes in an outer loop but is fixed during iteration in the inner loop. By using a partial, you don't have to pass in the additional parameter during iteration of the inner loop, because the modified (partial) function doesn't require it.</p> <pre><code>&gt;&gt;&gt; from functools import partial &gt;&gt;&gt; def fnx(a, b, c): return a + b + c &gt;&gt;&gt; fnx(3, 4, 5) 12 </code></pre> <p>create a partial function (using keyword arg)</p> <pre><code>&gt;&gt;&gt; pfnx = partial(fnx, a=12) &gt;&gt;&gt; pfnx(b=4, c=5) 21 </code></pre> <p>you can also create a partial function with a positional argument</p> <pre><code>&gt;&gt;&gt; pfnx = partial(fnx, 12) &gt;&gt;&gt; pfnx(4, 5) 21 </code></pre> <p>but this will throw (e.g., creating partial with keyword argument then calling using positional arguments)</p> <pre><code>&gt;&gt;&gt; pfnx = partial(fnx, a=12) &gt;&gt;&gt; pfnx(4, 5) Traceback (most recent call last): File "&lt;pyshell#80&gt;", line 1, in &lt;module&gt; pfnx(4, 5) TypeError: fnx() got multiple values for keyword argument 'a' </code></pre> <p>another use case: writing distributed code using python's <code>multiprocessing</code> library. A pool of processes is created using the Pool method:</p> <pre><code>&gt;&gt;&gt; import multiprocessing as MP &gt;&gt;&gt; # create a process pool: &gt;&gt;&gt; ppool = MP.Pool() </code></pre> <p><code>Pool</code> has a map method, but it only takes a single iterable, so if you need to pass in a function with a longer parameter list, re-define the function as a partial, to fix all but one:</p> <pre><code>&gt;&gt;&gt; ppool.map(pfnx, [4, 6, 7, 8]) </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload