3

Suppose I have the following class in Python 3:

class CoolCar:
    @classmethod
    def myWheels(cls):
        cls.Wheels().out()
    class Wheels:
        def __init__(self):
            self.s = "I'm round!"
        def out(self):
            print(self.s)

All well and good. Now I want a derived class:

class TerribleTank(CoolCar):
    class Wheels(CoolCar.Wheels):
        def __init__(self):
            self.s = "I'm square!!"

This works as I would expect:

CoolCar.myWheels()
TerribleTank.myWheels()

But what's bothering me is that I have to write CoolCar twice in the definition of TerribleTank. So I tried this:

class TerribleTank(CoolCar):
    class Wheels(super().Wheels):
        def __init__(self):
            self.s = "I'm square!!"

Which does not work. Now, I know it doesn't work because super() is looking for a first-argument self/cls to begin its search.

So finally my question: Is there something like this that works, so that I don't need to explicitly write that second CoolCar?

8
  • 2
    why are you putting classes in classes? Commented Jun 17, 2015 at 0:16
  • @PadraicCunningham: this is a greatly simplified example of what is actually going on. I am using subclasses for various reasons (namespace issues one of them), but also because it allows me to write Wheels.foo in one of my classes, and it simply works, with the right version of Wheels. For more information, please see the Factory Pattern chapter in Marc Summfield's Python in Practice. Commented Jun 17, 2015 at 0:21
  • Just declare Wheels as a class within the module, rather than encapsulating inside Coolcar. Surely Uncoolcars are entitled to wheels as well? Commented Jun 17, 2015 at 0:27
  • @JohnMee: TerribleTank will override this Wheel class. Now what does any class that inherits from TerribleTank do? Putting the original Wheels class at the module level only raises the problem one generation, it does not solve it. Commented Jun 17, 2015 at 0:34
  • I at least cannot see any way to use super how you want, Wheels knows nothing about CoolCar Commented Jun 17, 2015 at 0:45

1 Answer 1

2

What about:

class CoolCar:
    @classmethod
    def myWheels(cls):
        cls.Wheels().out()
    class Wheels:
        def __init__(self):
            self.s = "I'm round!"
        def out(self):
            print(self.s)

class TerribleTank(CoolCar):
    class Wheels(TerribleTank.Wheels):
        def __init__(self):
            self.s = "I'm square!!"

>>> TerribleTank.myWheels()
I'm square!!

basically when you inherit CoolCar in TerribleTank, you set up TerribleTank.Wheels as a reference to CoolCar.Wheels, until you shadow it with your own new definition of it within the TerribleTank definition. So I believe that matches your expectations of not having CoolCar twice in TerribleBank definition ☺

HTH

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

4 Comments

N.B.: If you're still unhappy about this because of the use of TerribleBank twice, you might try using metaclasses, but personally I'd rather go to bed than over-engineering something that simple ;)
Tweak it to call TerribleTank.myWheels() directly, he doesn't want to create tanks or cars; just their wheels.
This is technically correct (the best kind of correct), but I still hold hope there is a cleaner way to do this.
well, the cleaner way is what you suggested but does not fit you, this is what comes second, and then you might use some metaclass mess. But there's a saying: when you got a problem that needs metaclass to be solved, you end up having a metaproblem ;-)

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.