1

I've written a Python 3 metaclass containing a nested metaclass (with abc), like:

class A_M(object, metaclass=abc.ABCMeta):
    class A_nested_M(object, metaclass=abc.ABCMeta):
        def ... # some methods

Now, implementing like

class A(A_M):
     class A_nested(A_nested_M):
        def ...

doesn't work. So, did i miss something about usage of metaclasses or is this type of implementation with nested metaclasses not working at all?

4
  • 2
    Does it work if you inherit like this class A_nested(A_M.A_nested_M):? Commented Jun 28, 2017 at 11:23
  • A_nested_M is 'hidden' in A_M. Maybe you can access it with class A_nested(A_M.A_nested_M): ...? Commented Jun 28, 2017 at 11:24
  • Thanks! Somehow, this works with normal nested classes, but not metaclasses. As i said, did i miss something about the metaclass concept? Commented Jun 28, 2017 at 13:15
  • What are you actually trying to achieve? These snippets suggest some attempt that have no practical use at all. Commented Jun 28, 2017 at 20:30

2 Answers 2

4

First thing: Nesting class declarations is of near no use for anything in Python. Unless you are using the nested class hierarchy itself as a hard-coded namespace to keep attributes, you probably are doing the wrong thing already.

You did not tell what your (actual) problem is and what you are trying to achieve there, nor why you are using the ABCmeta metaclass. So it is hard to suggest any actually useful answers - but we can try clarifying some things:

First: you are not writting a metaclass, as you suggest in the text "I've written a Python 3 metaclass containing a nested metaclass..." - you are creating ordinary classes that have the ABCmeta as its metaclass. But you are not creating new metaclasses - You would if you were inheriting from type or from ABCMeta itself - them your new class would be used in the metaclass= parameter of subsequent (ordinary) classes. That is not the case.

Now, second, everything that is defined inside the body of your outermost A_M class will be only "visible" as attributes of A_M itself. That is the source of your error - when you try to inherit from A_nested_M you should actually write:

class A_M(object, metaclass=abc.ABCMeta):
    class A_nested_M(object, metaclass=abc.ABCMeta):
        def ... # some methods


class A(A_M):
     class A_nested(A_M.A_nested_M):
        def ...

See - A_M.A_nested_M will make Python find the superclass for A_nested: there is no reference in the local or global namespaces for A_nested_M as it only exists as an attribute of A_M outside the body of the class A_M... statement.

That said, this is still useless. If you want to have instances of A_nested referenced by instances of A class, you have to create these instances inside A.__init__() call - at which point it makes no difference if A_nested is declared inside a class body or at the module level:

class A_M(object, metaclass=abc.ABCMeta):
    pass

class A_nested_M(object, metaclass=abc.ABCMeta):
    def ... # some methods

class A_nested(A_nested_M):
   ...

class A(A_M):
    def __init__(self):
         self.nested = A_nested()

Now, that can be of some use. You can also declare the classes actually nested, but the only way they can be useful is by creating instances of them anyway. And unlike nested functions, nested classes do not have access to attributes or variables declared on the "nesting" class namespace (but for referring to them by their qualified name. I.e. in your example, if the A class would contain a b classmethod, a method inside A_nested that would call this method would have to call A.b(), not b())

Sign up to request clarification or add additional context in comments.

Comments

1

You should implement your class like this:

class A(A_M):
     class A_nested(A_M.A_nested_M):
        def ...

Because A_nested_M is an inner class, you should access it just like you would access any of the class attributes, i.e. A_M.A_nested_M. See this link.

2 Comments

This throws me an AttributeError: module 'A_M' has no attribute 'A_nested_M' .
@norb I'm not sure why it doesn't work with metaclasses. This will probably cost me some downvotes, but I will leave this answer for the time being, maybe someone knows the explanation why this doesn't work with metaclasses.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.