Combination of functools.partialmethod and classmethod
<p>I would like to use <code>functools.partialmethod</code> on a classmethod. However the behavior I find is not what I would expect (and like to have).
Here is an example:</p>

<pre><code>class A(object):
    @classmethod
    def h(cls, x, y):
        print(cls, x, y)

class B(A):
    h = functools.partialmethod(A.h, "fixed")
</code></pre>

<p>When I do</p>

<pre><code>&gt;&gt;&gt; b = B()
&gt;&gt;&gt; b.h(3)
</code></pre>

<p>I get an error:</p>

<pre><code>...
TypeError: h() takes 3 positional arguments but 4 were given
</code></pre>

<p>This is consistent with</p>

<pre><code>&gt;&gt;&gt; b.h()
&lt;class '__main__.A'&gt; &lt;__main__.B object at 0x1034739e8&gt; fixed
</code></pre>

<p>However, I would expect (and like to have) the following behavior:</p>

<pre><code>&gt;&gt;&gt; b.h(4)
&lt;class '__main__.B'&gt; fixed 4
</code></pre>

<p>I think that <code>functools.partialmethod</code> treats <code>B.h</code> as a normal instance method and passes the actual instance as first argument automatically.
But this behavior renders <code>functools.partialmethod</code> useless for freezing arguments in classmethods of inheriting classes.</p>

<p>Without going into too much detail, the <code>partial</code> object doesn't mix well with the descriptor protocol that <code>@classmethod</code> utilizes to create a class instance. The simple fix is to just define your overridden method in the usual fashion:</p>

<pre><code>class B(A):
    @classmethod
    def h(cls, y):
        return A.h("fixed", y)
</code></pre>

<hr>

<p>It <em>might</em> be possible to do what you want with some invocation of <code>partial</code>, but I was unable to find it. Here are some of my attempts, and why they failed.</p>

<p><code>A.h</code> invokes the <code>__get__</code> method of the function object, returning a function where the first argument is already bound to the calling class. <code>partial</code> then applies that function to <code>"fixed"</code>, but then the resulting callable <em>still</em> has a <code>__get__</code> method that tries to insert the calling class into the resulting call. You might try to work around that by defining <code>h</code> to actually be a <em>static</em> method:</p>

<pre><code>class B(A):
    h = staticmethod(partial(A.h, "fixed"))

&gt;&gt;&gt; B.h(4)
&lt;class '__main__.A'&gt; fixed 4
</code></pre>

<p>But as you can see, you already froze the class argument when you call <code>partial</code>. Another attempt is to avoid the descriptor protocol by accessing the argument directly:</p>

<pre><code>class B(A):
    h = staticmethod(partial(A.__dict__["h"], "fixed"))
</code></pre>

<p>but <code>classmethod</code> objects aren't actually callable; only the return value of their <code>__get__</code> methods is, so the call to <code>partial</code> fails.</p>

python python-3.x python-3.5 class-method functools