How do one class that is inside another inherit an instantiated variable from the last one in python?

Asked

Viewed 2,038 times

2

See the following python script:

class a:
        def __init__(self,n):
                self.n=n

        class b:
                def __init__(self):
                        ## o que botar aqui para receber a variável self.n ##
                def show(self):
                        return self.n
inst=a(3).b()
print(inst.show())

Class "b" is within class "a". Class "a" has an argument (other than self) and class "b" has none. I would like to know how to make class "b" inherit the variable "self. n" from class "a" so that it can be used in the "show" method. The goal is that this script shows the number 3.

  • What is the point of having an Internet class in your case? Explaining the problem may be that there is another way .

2 answers

4


Python requires explicitly creating the access

You must access the inner class through a function in the outer class.

Try it this way:

class externa(object):
    def __init__(self, n):
        self.n = n        

    def getInterna(self):
        return self.interna(self)

    class interna(object):
        def __init__ (self, pai):
            self.pai = pai

        def show(self):
            return self.pai.n

inst = externa(3).getInterna()

print(inst.show())
  • I understand what you put in there, but that’s not what I asked for. My goal is not to create a code that shows 3. It is to make the inner class receive a variable from the outer. In this example of yours, you didn’t even use the internal class. It could be deleted that there would be no difference in data output. The script I showed you is an example of how I want to solve my problem, my real script is very large and would be hard to understand if I were to put it all together. So I made it simple on that. @pagotti

  • 3

    That answer is correct. What you are trying to do is that you are not.

  • @Benedict if you notice in the penultimate instruction he takes the instance of the inner class calling getInterna().

  • It really was right. I don’t know what I had looked at. Obg.

2

Without understanding your problem is a complicated question to answer. The question doesn’t make much sense.

But come on - why do you want to declare one inner class to another? The class statement itself does not create objects of this class - the only difference is that to instantiate the class b, in the example you give, it is necessary to type a.b() - in this case Python searches inside the class a the attribute b verifica que é "chamável" - como não é uma função ordinária, essa chamada não ganha automaticamente o parâmetroself` which is put into methods.

That is, in :

class a:
    def b(self):
        ...

When you call b Python itself puts the attribute self there.

In your example, the class a.b is instantiated normally and will not know anything about the class a - much less about specific instances of the same.

The way to pass this reference is to instantiate the class in a method - which can be used as a "Factory" of objects a.b- That’s pretty much the same as in the other answer:

class a:
    def __init__(self):
         ...
    def b_factory(self):
         return self.__class__.b(self)

    class b:
         def __init__(self, instancia_pai):
               self.instancia_pai = instancia_pai
               print(self.instanca_pai.n)

You noted in the comment that "it doesn’t matter if the class b is within a" EXACTLY - because for any practical effect, it doesn’t matter. If a need to have instances of b attached to each instance, you can do this on your own __init__ - And the Python syntax allows you to declare classes inside each other, and use these classes as Namespaces for class attributes - but at the time you want to start creating instances of those classes, and have references to instances - (you want the attribute self.n of an instance of a), has to pass these instances as parameters for the methods.

The answer you want

Although it doesn’t make sense what you want to do, Python has a dynamic attribute engine called descriptors, which can be used to do whatever you need, but in the "right" way. Internally is the mechanism that Python uses to add the parameter self methods, and it is more common that it is used in user code with the Decorator property python.

It is as follows: every time Python recovers an attribute from a class, it checks whether that attribute exists first in the class (and not first in the instance) - if yes, it checks whether the attribute has the special method __get__. If you have, instead of continuing the search, Python calls this method __get__ passing the instance and class where the attribute was searched as parameters.

But then things get different. The method __get__ has to be the class of the recovered attribute. If the attribute itself is the class, it does not work. That is: to use descriptors classes have in their body instances of classes that have the method __get__ and not the classes themselves. You can even make the nested statement but, to function, you have to have an instance of the nested class, not the class itself in the body of a:

In short, your code can be written like this:

class a:
    def __init__(self,n):
        self.n=n

    class b:
        def __init__(self):
            ...

        def show(self):
            return self.instance.n

        def __get__(self, instance, owner):
             self.instance = instance
  c = b()

And with that code you can make: a(5).c.show() But not a(5).b.show() (and yes, realize that it doesn’t make any difference the statement of b be inside a - and yes, if I had called the instance c of b would anyway - only you would no longer have access to class b, only to a single instance created from it).

I’m not sure what you want to do with nested classes - but look at the documentation on descriptors, and will probably see that they are the ones who can do what you are wanting to do with the nested classes.

The official Python documentation on descriptors is extremely concise and is all here: https://docs.python.org/3.6/reference/datamodel.html#implementing-Descriptors

And in general, the class of Descriptors that comes ready, property, already does all that is necessary: https://docs.python.org/3/library/functions.html#Property

Browser other questions tagged

You are not signed in. Login or sign up in order to post.