How to register classes that inherit from an abstract class in python

Onturenio

I'm creating a module with a function that works as a factory of the implemented classes. It works registering the classes with the help of a metaclass (a pattern I have just copied from here).

  _registry = {}
  
  def register_class(cls):
      _registry[cls.__name__] = cls
  
  
  class Meta(type):
      def __new__(meta, name, bases, class_dict):
          cls = type.__new__(meta, name, bases, class_dict)
          register_class(cls)
          return cls
  
  def factory(name):
          return _registry[name]()

This works so far.

Now a particularity I have is that I'm implementing classes that share a lot of functionality, therefore I define an abstract base class that implements most of the shared logic, and a large number of derived classes that refine certain particularities. The problem is that this leads to a metaclass conflict, as the metaclass of the the derived classes is both ABCmeta and Meta:

  from abc import ABC, abstractmethod
  
  _registry = {}
  
  def register_class(cls):
      _registry[cls.__name__] = cls
  
  
  class Meta(type):
      def __new__(meta, name, bases, class_dict):
          cls = type.__new__(meta, name, bases, class_dict)
          register_class(cls)
          return cls
  
  def factory(name):
          return _registry[name]()
  
  class Base(ABC):
      pass
  
  class Derived1(Base, metaclass=Meta):
      pass

  TypeError: metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases
            

How can I work around this conflict?

jsbueno

Simply combine the metaclasses you need into a suitable, derived, metaclass, and use that one as your metaclass. In this case, jsut derive your metaclass from "ABCMeta" instead of type:


from abc import ABCMeta

  class Meta(ABCMeta):
      def __new__(meta, name, bases, class_dict):
          cls = super().__new__(meta, name, bases, class_dict)
          register_class(cls)
          return cls

Note the importance of using super().__new__ instead of type.__new__ - that is the requisite for our metaclass to be able to be combined with other metaclasses (as far as none of them interfere directly in the same attributes/logic your own metaclass is working on).

So, if you'd need some of your classes to use ABCMeta, and some that would use your metaclass alon, you could, just by replacing the call to type.__new__ with super().__new__ use your metaclass as a mixin, to combine the ABCMeta as needed:

from abc import ABCMeta


class Meta(type):
   ...

class MetaWithAbc(Meta, ABCMeta):
    pass

class Base(metaclass=MetaWithAbc):
    pass

...

Also, since Python 3.6, the need for metaclasses has reduced considerably with the introduction of the special __init_subclass__ method. To simply add a class to registry, as in this case, there is no need for a custom metaclass, if you have a common baseclass: __init_subclass__ is called once per subclass, as it is created:

  from abc import ABC, abstractmethod
  
  _registry = {}
  
  def register_class(cls):
      _registry[cls.__name__] = cls
  
  def factory(name):
          return _registry[name]()
  
  class Base(ABC):
      def __init_subclass__(cls, **kwargs):
          # always make it colaborative:
          super().__init_subclass__(cls, **kwargs)
          register_class(cls)
  
  
  class Derived1(Base):
      pass

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

How to make an Abstract Class inherit from another Abstract Class in Python?

From Java

Making an abstract class inherit from another abstract class in python

From Java

How to call abstract method from abstract class called by inherit class

From Java

Inherit annotations from abstract class?

From Dev

How to test an object class inherit from a certain abstract class

From Dev

How to inherit abstract class with PyCharm

From Dev

Should a python abstract base class inherit from object

From Dev

Node.js: how to 'inherit' from abstract class?

From Dev

How to inherit from an abstract class properly in C++?

From Dev

Is it possible to inherit from multiple abstract classes in Java?

From Dev

Can child classes inherit instance variables from their parent class in Python?

From Dev

Inherit INotifyPropertyChanged for Static Event from abstract Class

From Dev

How to use super() to inherit a particular class from multiple father classes?

From Dev

Python - Inherit from class which inherit Model

From Dev

How access properties of Inherited classes from abstract class

From Dev

How to force overrides in a derived class from non abstract base classes?

From Dev

How can I retrieve the derived class from a list of abstract classes?

From Dev

How to inherit from SQLAlchemy classes and own classes

From Dev

How to inherit multiple instances of a class from a single class in python

From Dev

Class that can inherit from two different classes

From Dev

Mock class which inherit from abstract class and implements interface

From Java

How to create abstract properties in python abstract classes

From Dev

How to get a class to inherit from all of the same classes that another class does

From Javascript

How to inherit from a class in javascript?

From Dev

Correct way to inherit from Abstract class with dependent interfaces in C#

From Dev

Is there a way to inherit from a (preferably abstract) base razor class?

From Dev

Doxygen - Inherit documentation from externally documented abstract class

From Dev

@abstractmethod given by a second class to inherit from (multiple inheritance with abstract methods)

From Dev

How to inherit from a pure Python class in Odoo to modify a method?

Related Related

  1. 1

    How to make an Abstract Class inherit from another Abstract Class in Python?

  2. 2

    Making an abstract class inherit from another abstract class in python

  3. 3

    How to call abstract method from abstract class called by inherit class

  4. 4

    Inherit annotations from abstract class?

  5. 5

    How to test an object class inherit from a certain abstract class

  6. 6

    How to inherit abstract class with PyCharm

  7. 7

    Should a python abstract base class inherit from object

  8. 8

    Node.js: how to 'inherit' from abstract class?

  9. 9

    How to inherit from an abstract class properly in C++?

  10. 10

    Is it possible to inherit from multiple abstract classes in Java?

  11. 11

    Can child classes inherit instance variables from their parent class in Python?

  12. 12

    Inherit INotifyPropertyChanged for Static Event from abstract Class

  13. 13

    How to use super() to inherit a particular class from multiple father classes?

  14. 14

    Python - Inherit from class which inherit Model

  15. 15

    How access properties of Inherited classes from abstract class

  16. 16

    How to force overrides in a derived class from non abstract base classes?

  17. 17

    How can I retrieve the derived class from a list of abstract classes?

  18. 18

    How to inherit from SQLAlchemy classes and own classes

  19. 19

    How to inherit multiple instances of a class from a single class in python

  20. 20

    Class that can inherit from two different classes

  21. 21

    Mock class which inherit from abstract class and implements interface

  22. 22

    How to create abstract properties in python abstract classes

  23. 23

    How to get a class to inherit from all of the same classes that another class does

  24. 24

    How to inherit from a class in javascript?

  25. 25

    Correct way to inherit from Abstract class with dependent interfaces in C#

  26. 26

    Is there a way to inherit from a (preferably abstract) base razor class?

  27. 27

    Doxygen - Inherit documentation from externally documented abstract class

  28. 28

    @abstractmethod given by a second class to inherit from (multiple inheritance with abstract methods)

  29. 29

    How to inherit from a pure Python class in Odoo to modify a method?

HotTag

Archive