0

Say a meta‑class A expects parameters. A class B of this meta‑class, will have to assign these parameters. Say this class B is to be a base class, and that's its imediat derived classes which are expected to assign these parameters. Is this feasible if this makes sense? If ever this does not make sense, so why?

With the hope it will help to understand the question, here is an extract of the concrete case (which does not pretend to be marvelous), where only the relevant parts are shown (not strictly valid Python, due to place‑holders). Please note this example is valid with Python 3, and I'm not sure it is with the prior Python version (a point I'm adding after a comment).

class Type(type)
    def __new__(…, elements)
    …

class ArrowType(Type):
    def __new__(…, domain, codomain)
        # This build a suitable `elements`
        # parameter, from its own arguments,
        # for the call to `Type.__new__`
    …

class Function(
        object, 
        metaclass=ArrowType, 
        domain=…, 
        codomain=…)
    …

Say the Function class is expected to be a base class, but it's not concrete. It's abstract with regard to its domain and codomain parameters, intended to ArrowType. Say there is no defaults justified, and providing defaults in the vein of None or () or who‑know what, is not considered good (looks like a hack to me).

I tried to make Function abstract, but failed to get a solution from this, as the parameters still needs to be instantiated at the point of Function's definition. Or may be I did it erroneously?

Well, I could use a function:

def function(domain, codomain):
    class Function(
            object, 
            metaclass=ArrowType, 
            domain=domain, 
            codomain=codomain)
        …
    return Function

This works, but I don't like it, for multiple reasons: 1) Function is “hidden” in a function body, 2) this is not anymore a single base class (and neither really abstract), as it ends into as many base classes as there are classes derived from it (function being invoked for each), 3) the class‑names the instances gets as displayed by type(…), are ugly.

In few words, what's expected, is to have Function to be abstract, with respect to its domain and codomain parameters, which would be assigned something in its derived only classes.

Hibou57
  • 6,870
  • 6
  • 52
  • 56
  • The `class` statement, as implemented in Python, does not allow you to pass extra arguments to the `__init__` method of your metaclass. You would have to call it more explicitly (well, less implicitly, anyway), with something like `Function = ArrowType('Function', domain, codomain)`. – chepner Sep 11 '14 at 22:19
  • @chepner, well, to `__new__`, but as `__new__` and `__init__` typically gets the same parameters, I used `__init__`, which is more common. The comment is still worth, and I will edit the question to change `__init__` into `__new__`. – Hibou57 Sep 11 '14 at 22:21
  • The point is that the metaclass, as called by the execution of the `class` statement, *always* calls it with just 3 arguments: the name of the class, a tuple of base classes, and a dictionary containing everything in the body of the `class` statement. There's no syntax for adding more arguments. – chepner Sep 11 '14 at 22:22
  • @chepner, May be a matter of Python version? I'm using Python 3.4, and I'm really using parameters which are received by `__new__` and the class gets instantiated without an error. I'm adding a note on Python version in the question. – Hibou57 Sep 11 '14 at 22:29
  • Retracted. For some reason, I was having trouble finding the documentation for metaclasses in Python 3. I see that additional keyword arguments to the class are passed to the metaclass. – chepner Sep 12 '14 at 11:52

0 Answers0