2

In Python, what are the pros and cons of implementing an abstract method using a static method?

For example,

import numpy as np


class ExponentialFamily:

    @abstractmethod
    def log_normalizer(self, q):
        raise NotImplementedError


class Multinomial(ExponentialFamily):

    @staticmethod
    def log_normalizer(q):
        max_q = np.maximum(0.0, np.amax(q))
        q_minus_max_q = q - max_q
        return max_q + np.logaddexp(-max_q, np.logaddexp.reduce(q_minus_max_q))

class NegativeBinomial(ExponentialFamily):

    def __init__(self, r):
        super().__init__()
        self.r = r

    def log_normalizer(self, q):
        return -self.r * np.log1p(-mf.exp(q))

On the one hand, I know that pylint will complain less about self being unused. On the other hand, it seems weird to use staticmethod here.

In a situation of cooperative multiple inheritance, I could not use staticmethod because I would need at least the true type to call super, and the superclass might want the self object. However, this is not such a situation.

Neil G
  • 32,138
  • 39
  • 156
  • 257
  • can you clarify your concern? there is nothing inherently wrong with your code. Multinomial will be instantiated correctly because it implements log_normalizer. – Manu Valdés Mar 14 '19 at 10:34
  • 1
    @ManuValdés Does it not seem very weird to you? It seems weird to me. I'm wondering if I'm missing something. I know that Guido once said that he regretted adding `statimethod` to the language at all. – Neil G Mar 14 '19 at 10:36
  • 1
    All it really does is suppress the implicit first argument. If you don't need `self` in the method, why not suppress it…? – deceze Mar 14 '19 at 10:41
  • 1
    I don't think it's particularly weird. Other functions would use the `log_normalizer` method in the same way whether it was a static method or not. – Manu Valdés Mar 14 '19 at 10:51
  • I might be missing something here, but why not add the `@staticmethod` decorator above the `@abstractmethod` decorator in `ExponentialFamily`? Raises the expected `TypeError` on instantiation of descendants when using `ABCMeta` as metaclass, keeps the signatures in sync and makes it clear that this method is supposed to be implemented statically. – shmee Mar 14 '19 at 11:40
  • @shmee I guess I should have been clearer, but some of the subclasses do implement the method non-statically. – Neil G Mar 14 '19 at 11:41
  • @NeilG Ah! I missed that indeed :) – shmee Mar 14 '19 at 11:43
  • 1
    @shmee I've added an example, so thanks! – Neil G Mar 14 '19 at 11:43

1 Answers1

4

On a purist OOP point of view, overriding a normal method with a static one is just heretic. But because of the way Python processes methods, it is perfectly allowed by the language.

I will try a list of pro/con:

Pros:

  • makes explicit that log_normalizer in Multinomial is independant of the instance
  • saves a pylint warning

Cons:

  • OOP heretic. Purists will shout after you
  • disturbing design for programmers used to non dynamic languages like C++ or Java
  • uncommon design, that IMHO requires comments explaining the rationale for future readers/mantainers
  • maybe a consequence of a questionnable design: how can a method be non static in a base class (abstract should not matter) and static in a subclass
Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252