0

My Parent class has a cat and a dog, and I need the dog to execute a function in the cat class.

Also, cat and dog need to be inner nested classes inside the parent class.

I read that dog needs to use super() to call the parent class, and then use his cat instance. But it doesn't works.

I get the error

TypeError: super(type, obj): obj must be an instance or subtype of type

_

Animal = Parent()
Animal.ThisDog.BarkToCat()

class Parent(object):   

    def __init__(self, *args, **kwargs):
        self.ThisCat = self.cat()
        self.ThisDog = self.dog()

    class cat(object):
        def barked(self):
            return ("I better run!")

    class dog(object):
        def BarkToCat(self):
            print(super(Parent,self).ThisCat.barked())

I cannot write dog(Parent)

class dog(Parent):
    def BarkToCat(self):
        print(super(Parent,self).ThisCat.barked())

... because I get the error

NameError: name 'Parent' is not defined

I'm lost. How is this done in Python?

Stephen Docy
  • 4,738
  • 7
  • 18
  • 31
jonuko
  • 39
  • 1
  • 5
  • 2
    Why do you think `cat` and `dog` need to be nested classes? It looks like you've misunderstood all 3 of nested classes, subclasses, and `super`. – user2357112 Apr 18 '18 at 23:37
  • I need what the accepted answer says here https://stackoverflow.com/questions/719705/what-is-the-purpose-of-pythons-inner-classes – jonuko Apr 18 '18 at 23:39
  • It makes clear that cat only exists inside Parent. It is stuff used inside Parent – jonuko Apr 18 '18 at 23:40
  • I think you just don't need `super()` to access `ThisDog` from a `ThisCat`, and vice versa. (Can't help but notice that inheritance should be used with great caution, and composition is [almost always a better approach](https://en.wikipedia.org/wiki/Composition_over_inheritance).) – 9000 Apr 18 '18 at 23:42
  • 1
    @user2357112 If I read this code many years in the future, I will immediately understand that cats and dogs are related to Parent. Anybody would rapidly understand how it works. It makes the code maintainable. – jonuko Apr 18 '18 at 23:43
  • You can't see it, but the accepted answer there has 17 downvotes. It's a terrible fit for Python; it only makes sense for other languages. It stays vote-positive because people upvote without enough domain knowledge to realize the answer is bad. – user2357112 Apr 18 '18 at 23:43
  • 1
    You're trying to write Python as if it's Java, as if inner classes automatically had a reference to the outer and as if `super(Parent, self)` were Java's `OuterClass.this`. Python isn't Java, and patterns that make sense in Java don't make sense in Python. – user2357112 Apr 18 '18 at 23:45
  • To add to @user2357112's comment: in Python, classes are poor namespaces. Modules are proper namespaces. – 9000 Apr 18 '18 at 23:45
  • @user2357112 The answer isn't bad. That is why all languages allow nested classes, and that is why I want it. The downvotes are not relevant. The people who downvoted, doens't know why nested classes exist in any language. – jonuko Apr 18 '18 at 23:46
  • @user2357112 Python allows nested classes, so "why" is off topic. The point is, since it is allowed, how is it used. – jonuko Apr 18 '18 at 23:48
  • @jonuko: offtpic, but have you ever heard about the Dunning-Kruger curve? On topic: yes, nested classes would work. No, you can't use `super` to access the outer class's instance. You have to explicitly pass it. There's _no_ automatic mechanism to do it (as it's done in Java). If you did it explicitly, everything would work; a factoty method in `Parent` would be a good way to construct cats and dogs linked to a particular Parent instance. Think of cats and dogs having private constructors, only available to Parent, which passes itself as a parameter. – 9000 Apr 18 '18 at 23:49
  • @user2357112 Is not relevant in the least that Python isn't java. I need a nested class no matter if Java exists or not, because that's the point of nested classes. Python allows nested classes, so it needs a way to make it work. The existence of Java changes nothing. – jonuko Apr 18 '18 at 23:52
  • @9000 Ok. That's a bit rude, but if you are saying that it cannot be done, I may take it as answer. Please don't mention Java. I'm not a Java programmer, and this question has nothing to do with Java. – jonuko Apr 18 '18 at 23:57
  • @jonuko: This can be done, but not in an automatic way. Java just happens to have a well-developed mechanism for inner classes, so it gets mentioned, as an example. I'll try to write a proper answer when I have a moment. – 9000 Apr 19 '18 at 01:05

2 Answers2

0

Here's an example of a nested class, and linking in instance of outer and nested classes explicitly. No magic.

class Parent(object):

    def __init__(self, name):
        self.name = name
        self.dog = self.adopt_dog()

    def walk(self):
        print('%s walks, and %s goes %s' % (
            self.name, self.dog.name, self.dog.bark()))

    def adopt_dog(self):
        # Refer to an attrubute of the class Parent,
        # which happens to be another class, Dog.
        return self.__class__.Dog(self, '%s\'s dog' % self.name)

    # Now the namespaced class.

    class Dog(object):
        def __init__(self, master, name):
            self.master = master
            self.name = name

        def bark(self):
            return 'bark!'

Try it:

>>> joe = Parent('Joe')
>>> joe.walk()
Joe walks, and Joe's dog goes bark!
>>> joe.dog.master is joe
True
>>> _
9000
  • 39,899
  • 9
  • 66
  • 104
  • It goes halfway, but is Joe talking to his dog, instead of Joe's dog talking to Joe's cat. Anyways, I used a similar solution, and I posted it as answer – jonuko Apr 21 '18 at 08:50
  • Sure you can add a cat, so that the cat would address the dog as `self.master.dog` from within its methods. The key idea is the `master` link. – 9000 Apr 21 '18 at 16:30
0

I found a way for cat and dog to talk to each other, which is to make the parent explicit inside dog and cat

class HasParent(object):
    def __init__(self, Parent=None):
        if (Parent is None):
            raise Exception("I need a parent!")
        self.Parent=Parent

class Parent(object):   

    def __init__(self):
        self.ThisCat = self.cat(Parent = self)
        self.ThisDog = self.dog(Parent = self)

    class cat(HasParent):

        def barked(self):
            return ("I better run!")

    class dog(HasParent):

        def BarkToCat(self):
            print(self.Parent.ThisCat.barked())


Animal = Parent()
Animal.ThisDog.BarkToCat()
jonuko
  • 39
  • 1
  • 5