2
class A:
    class B(A):
        pass

This does not work. Why? How do I make something that behaves the same way?

By same I mean:

  • The same __class__.__name__
  • The same __class__.__qualname__
  • A.B.__base__ is A
Hristo Venev
  • 972
  • 5
  • 17
  • What error does it throw? If it's `name A not defined`, it's because the definition of `A` isn't done by the time `B` is beginning to get defined. – TankorSmash Jan 28 '14 at 21:04
  • @TankorSmash: `line 2: NameError: name 'A' is not defined`. – Hristo Venev Jan 28 '14 at 21:06
  • Why are you declaring class B inside A, and having B inherit from A? I would think you'd want to declare B outside of A. – forgivenson Jan 28 '14 at 21:07
  • 4
    Why would you want this? Nested classes are already mostly nonsensical in Python, but a nested class inheriting from the outer class is exotic (though legal) even in Java, C# and the like. –  Jan 28 '14 at 21:08
  • 1
    Sup dawg, I heard you like classes. – BrenBarn Jan 28 '14 at 21:10
  • `A` is supposed to represent a very specific set of objects. `B` is a variation of `A`. `A` has a method `b(self)` which converts it to a `B`. – Hristo Venev Jan 28 '14 at 21:13
  • 4
    @HristoVenev: That still doesn't explain why you need B inside A. – BrenBarn Jan 28 '14 at 21:15

3 Answers3

8

No, not without workarounds. The first class doesn't even exist at the time its body (including the class B(A) part) is executed. You can define the two separtely though:

class A:
    pass

class B(A):
    pass

A.B = B
B.__name__ = ...
B.__qualname__ = ...

But honestly this doesn't look like the best design or API.

1

Evaluation happens "inside out". Class A is not created until after everything in its class body is done. So at the time B is defined, A does not yet exist.

Your only option would be to define class B with some other base class, then write a class decorator or metaclass on A that looks inside A for attributes that are classes with the specified "dummy" base, and recreates them with A as their base.

The real question is why you feel you need to do this.

BrenBarn
  • 242,874
  • 37
  • 412
  • 384
0

Just because metaclasses are amusing:

class GoofyMeta(type):
    def __new__(cls, clsname, bases, dct):
        dct['__qualname__'] = bases[0].__qualname__
        return super(GoofyMeta, cls).__new__(cls, bases[0].__name__, bases, dct)

class A:
    pass

#using python 3 syntax here
class B(A,metaclass=GoofyMeta):
    pass

B.__name__
Out[24]: 'A'

B.__qualname__
Out[25]: 'A'

And B.__base__ is A by definition.

As for why you'd want this, I'm pretty mystified. It seems like you can just use inheritance/composition normally like the rest of us :-)

(I'll also note that I didn't address B somehow being an inner class of A. I extra plus one don't know what you're trying to do with that.)

roippi
  • 25,533
  • 4
  • 48
  • 73