How to inherit classmethod constructors?

Peter Otten __peter__ at web.de
Sat Feb 18 15:20:41 EST 2017


Daniel Andersson wrote:

> 
> I have a class "A" below, that have a very simple
> __init__ method, which only wants a "needle".
> 
> 
> class A:
>     def __init__(self, needle):
>         self.needle = needle
> 
>     @classmethod
>     def from_haystack(cls, haystack):
>         # ...
>         # Many lines of code (omitted here)
>         # that process haystack to obtain a needle
>         # ...
>         # ...
>         # The obtained needle is then used to
>         # return an instance
>         return cls(needle)
> 
> 
> The class also has a classmethod: "from_haystack"
> that is used as an alternative to __init__ for
> initalizing an instance.
> 
> My problem is that:
>   1. I'm not allowed to refactor A.
>   2. I need a class B which must inherit A.
>   3. B must use a haystack to initialize
>      itself.
>   4. Therefore, I want to reuse "from_haystack" from A
>      in some way so I don't have to repeat the code.
> 
> My naive solution was this:
> 
> 
> class B(A):
>     def __init__(self, haystack, spam, eggs):
>         super().from_haystack(haystack)  # Won't work
>         self.spam = spam
>         self.eggs = eggs
> 
> 
> The use of super() here will call "from_haystack" with
> cls = B, which won't work, since the return line will be
> "return B(needle)" and B can't handle that.
> 
> What is idiomatic solution to this problem?

If A is a heap class you can change the class after the from_haystack() 
invocation:

class B(A):
    def __new__(cls, needle, spam, eggs):
        inst = A.from_haystack(needle)
        inst.__class__ = cls
        return inst

    def __init__(self, needle, spam, eggs):
        super().__init__(needle)
        self.spam = spam
        self.eggs = eggs





More information about the Python-list mailing list