Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to subclass ABCMeta

Normally, to subclass a class I do something like

class Subby(Parenty):
    def __init__(self):
        Parenty.__init__(self)

But now I'm trying to subclass a metaclass, specifically ABCMeta, so I'm doing

import ABCMeta

class Subby(ABCMeta):
    def __init__(self):
       ABCMeta.__init__(self) #this never seems to run

    def __new__(mcls, name, bases, namespace):
        cls = ABCMeta.__new__(mcls, name, bases, namespace)
        return cls

But, when I then try to subclass Subby as a metaclass like

class newClass(metaclass=Subby):
    pass

I get the error TypeError: __init__() takes 1 positional argument but 4 were given.

Why is this, and how do I subclass ABCMeta correctly?

like image 901
Pro Q Avatar asked Oct 17 '22 12:10

Pro Q


1 Answers

From the datamodel:

If __new__() returns an instance of cls, then the new instance’s __init__() method will be invoked like __init__(self[, ...]), where self is the new instance and the remaining arguments are the same as were passed to __new__().

So, as @user2357112 said, the signatures must match.

Despite this, there's really no reason to define __init__ and __new__ if you simply want to create an ABC. Just create it and use .register to register the conforming classes. Optionally, create a number of abstract methods and a __subclasshook__ that checks for conformance. A good example already exists in the abc module documentation.

like image 190
Dimitris Fasarakis Hilliard Avatar answered Oct 21 '22 04:10

Dimitris Fasarakis Hilliard