Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<blockquote> <p>What functionality does functools.partial offer that you can't get through lambdas?</p> </blockquote> <p>Not much in terms of extra <em>functionality</em> (but, see later) -- and, readability is in the eye of the beholder.<br> Most people who are familiar with functional programming languages (those in the Lisp/Scheme families in particular) appear to like <code>lambda</code> just fine -- I say "most", definitely <em>not</em> all, because Guido and I assuredly are among those "familiar with" (etc) yet think of <code>lambda</code> as an eyesore anomaly in Python...<br> He was repentant of ever having accepted it into Python whereas planned to remove it from Python 3, as one of "Python's glitches".<br> I fully supported him in that. (I love <code>lambda</code> <em>in Scheme</em>... while its limitations <em>in Python</em>, and the weird way it <em>just doesn't fit in</em> with the rest of the language, make my skin crawl).</p> <p>Not so, however, for the hordes of <code>lambda</code> lovers -- who staged one of the closest things to a rebellion ever seen in Python's history, until Guido backtracked and decided to leave <code>lambda</code> in.<br> Several possible additions to <code>functools</code> (to make functions returning constants, identity, etc) didn't happen (to avoid explicitly duplicating more of <code>lambda</code>'s functionality), though <code>partial</code> did of course remain (it's no <em>total</em> duplication, nor is it an eyesore).</p> <p>Remember that <code>lambda</code>'s body is limited to be an <em>expression</em>, so it's got limitations. For example...:</p> <pre><code>&gt;&gt;&gt; import functools &gt;&gt;&gt; f = functools.partial(int, base=2) &gt;&gt;&gt; f.args () &gt;&gt;&gt; f.func &lt;type 'int'&gt; &gt;&gt;&gt; f.keywords {'base': 2} &gt;&gt;&gt; </code></pre> <p><code>functools.partial</code>'s returned function is decorated with attributes useful for introspection -- the function it's wrapping, and what positional and named arguments it fixes therein. Further, the named arguments can be overridden right back (the "fixing" is rather, in a sense, the setting of defaults):</p> <pre><code>&gt;&gt;&gt; f('23', base=10) 23 </code></pre> <p>So, as you see, it's <em>definely</em> not as simplistic as <code>lambda s: int(s, base=2)</code>!-)</p> <p>Yes, you <em>could</em> contort your lambda to give you some of this -- e.g., for the keyword-overriding,</p> <pre><code>&gt;&gt;&gt; f = lambda s, **k: int(s, **dict({'base': 2}, **k)) </code></pre> <p>but I dearly <strong>hope</strong> that even the most ardent <code>lambda</code>-lover doesn't consider <em>this</em> horror more readable than the <code>partial</code> call!-). The "attribute setting" part is even harder, because of the "body's a single expression" limitation of Python's <code>lambda</code> (plus the fact that assignment can never be part of a Python expression)... you end up "faking assignments within an expression" by stretching list comprehension well beyond its design limits...:</p> <pre><code>&gt;&gt;&gt; f = [f for f in (lambda f: int(s, base=2),) if setattr(f, 'keywords', {'base': 2}) is None][0] </code></pre> <p>Now combine the named-arguments overridability, plus the setting of three attributes, into a single expression, and tell me just how readable <em>that</em> is going to be...!-)</p>
 

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