3

Given PEP 560, why do generic types still use a metaclass in Python?

In [8]: from typing import Generic, TypeVar

In [10]: type(Generic[T])  

Out[10]: typing._GenericAlias

In [11]: type(Generic[T]).__mro__   

Out[11]: (typing._GenericAlias, typing._Final, object)

My problem is that I want to define a set subclass:

T = TypeVar('T')


class Selection(abc.MutableSet, MutableSet[T], QObject):
    """
    A MutableSet that emits QEvents
    """

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.selection: Set[T] = set()

but I get the error:

TypeError: metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases
Neil G
  • 32,138
  • 39
  • 156
  • 257
  • 1
    Whether `Generic[T]` uses a metaclass or not should be irrelevant; what you should be checking is `type(Generic)`. – Aran-Fey Mar 19 '19 at 07:50
  • @Aran-Fey But I want to inherit from `Generic[T]`? What have I misunderstood? – Neil G Mar 19 '19 at 07:50
  • Oh yeah, you're right. The `typing` module is so counterintuitive... – Aran-Fey Mar 19 '19 at 07:52
  • @Aran-Fey I know. I really don't get it. Anyway, I've added my exact problem. – Neil G Mar 19 '19 at 07:54
  • From what I understand the problem is inheriting from different metaclasses so `Selection` doesn't know which one to pick, you need to explicitly create a single class that can be used as the metaclass, see (for e.g.) https://stackoverflow.com/q/46837947/458741 and https://stackoverflow.com/q/28720217/458741 – Ben Mar 19 '19 at 07:59
  • @Ben I understand that, but that's too hard since I don't know what these generic metaclasses are doing. Which is why I'm asking why `typing` needs a metaclass anyway? – Neil G Mar 19 '19 at 08:01
  • Why do you create such a big stack of inheritance? Why don't you use a subclass of QList or QVector which emit signals or events?... I ask because of your docstring. – Sven-Eric Krüger Mar 19 '19 at 08:03
  • Because `QList` and `QVector` are very badly designed, non-Pythonic, don't have typing information, and don't interact well with Python types. Does `QSet` even inherit from `abc.MutableSet`? – Neil G Mar 19 '19 at 08:06
  • 1
    This isn't even really a metaclass; it's something arguably weirder. `Generic[T]` *isn't a class*, and `typing._GenericAlias` isn't a metaclass, but the `class` statement has been designed to allow listing things that aren't classes as base classes. – user2357112 Jun 22 '19 at 02:33

0 Answers0