Nested Functions in Python

Asked

Viewed 881 times

3

How do I do nested functions in Python? Another question, because I always need to use the self parameter, and I’ve already put parameters in the function?

For example, it is considered that the function gerar_individuo() is already implemented and that I need to create a function called gerar_populacao(self, individual) as below:

def gerar_populacao(self, individuo):
        tamanho_populacao = 100
        while(tamanho_populacao > 0):
            individuo = gerar_individuo(linha_do_tempo, linha_do_tempo, disciplinas)

When I execute my code gives error:

Undefined variable 'generat_individual'

Undefined variable 'line_do_tempo'

Undefined variable 'disciplines'

From what I can tell, he is not recognizing the function gerar_individuo() as being an external reference. How do I resolve this?

# aqui está todo o código:

import time
import random
import copy

class AG():

cs = []
gav = ["A01", "A02", "A03", "A04", "A05", "A06", "A07", "A08"]                              
icc = ["A02", "A08"]
lc = ["A09", "A10", "A11", "A12", "A13", "A01", "A02"]
oc = ["A14", "A15", "A16", "A17", "A18", "A19", "A20", 
"A21", "A22", "A23", "A24", "A25", "A26", "A27", "A28", "A29", "A30", 
"A31", "A32", "A33", "A34", "A35", "A36", "A37", "A38", "A39", "A40" ,
"A01", "A02", "A04", "A08"]
pcal = ["A40", "A41", "A42", "A43", "A44", "A45", "A46", "A47", "A48",
"A49", "A50", "A51", "A52", "A53", "A54", "A55", "A56", "A57", "A58", 
"A59", "A60", "A61", "A62", "A63", "A64", "A65", "A66", "A67", "A68", 
"A01", "A02", "A03", "A05", "A08"]
pc1 = ["A69", "A70", "A71", "A72", "A73", "A74", "A01", "A02", "A08"]

#codigos das disciplinas
_cs = 1101
_gav = 1102
_icc = 1103
_lc = 1104
_oc = 1105
_pcal = 1106
_pc1 = 1107

disciplinas = [_cs, _gav, _icc, _lc, _oc, _pcal, _pc1]

primeiro_ano = [1101, 1102, 1103, 1104, 1105, 1106, 1107]
segundo_ano = [2101, 2102, 2103, 2104, 2105, 2106, 2107, 2108]
terceiro_ano = [3101, 3102, 3103, 3104, 3105, 3106, 3107, 3108]
quarto_ano = [4101, 4102, 4103, 4104, 4105, 4106, 4107]

linha_do_tempo = []
TAM =  80

def __init__(self):
    self.linha_do_tempo = self.zero_list_maker(self.TAM)
    print ("Inicializando a linha do tempo...")
    print ("Linha do tempo: ", self.linha_do_tempo)

def zero_list_maker(self, length):
    listofzeros = [0] * length
    return listofzeros

def gerar_populacao(self):    
    populacao = []
    tamanho_populacao = 100
    lCount = len(self.linha_do_tempo)
    while(tamanho_populacao > 0):
        # para nao alterar as listas originais fazemos um copy delas para cada individuo
        discis = copy.deepcopy(self.disciplinas)
        linha_tempo = copy.deepcopy(self.linha_do_tempo)
        randDisc = []
        next1 = False
        for i in range(0, lCount-1):
            if(len(discis) > 0):
                position = random.randint(0,lCount-1)
                disc = random.choice(discis)
                if(linha_tempo[i] == 0 and linha_tempo[i+1] == 0):
                    linha_tempo[position] = disc
                    randDisc.append(disc)
                    discis.remove(disc)
                    next1 = True
                elif(next1):
                    linha_tempo[position] = disc
                    randDisc.append(disc)
                    discis.remove(disc)
                    next1 = False
                else:
                    break
            populacao.append(linha_tempo)
        tamanho_populacao -= 1
    return populacao

ag = AG() population = ag.gerar_population() print(population) first individuo = population[0] print(' n nFirst person: n', first individual)

  • 1

    The problem is not the function, it is the variable linha_tempo that is not defined. And why does it repeat? Self is if these functions belong to an object/class. They are within a class?

  • I understood friend =) yes, everything is within one class only. It’s like this: I made a function generate individual with the code you made, as it is above, where I step by parameter the line_do_tempothat was initialized with 80 zero positions:

  • line_do_time = [0] * 80

  • 1

    this function generate individual returns something? if print individual after that will have worked

  • 1

    but it should declare time line within the function to generate population, before the while

  • and the list of disciplines, which contains all disciplines. I randomized them, according to their code, in the timeline. Now I need to generate a list of individuals, e.g. 100 different timelines and store in a list.

  • 1

    Maybe it would be easier if you put in all the relevant code so we can help you

  • Jewel, I’ll do it then in another question =)

  • Okay, buddy, I edited my question up there, and I added all the code. I tried to do a while() with population size and print the result, but did not generate anything xD

  • 1

    Why are you calling gerar_populacao with two linha_do_tempo?

  • If I remove the first time string parameter does not work, it generates an error saying that the self parameter has not been initialized. The following error appears: No value for argument 'disciplines' in method call

  • I am doing the project in C9.io because it is tcc I preferred to do in the cloud. How do I reference you in my tcc? I will thank you for the help!

  • 1

    There’s no need @Allan. I’m from Portugal, here it’s late, bedtime. Tomorrow at work I will come back here and if there is no solution we have solved this problem. It can be?

  • Yes friend, you can leave! As for the fact that you are from Portugal, there is no problem, because my theoretical background is in an article by a Professor. from Portugal =) Profª Paula Amaral from the University of Lisbon :D good rest friend, thanks even for the help!

Show 10 more comments

1 answer

3


@Allan here goes. The problem is that when we are accessing properties/methods within the class we have to use the prefix/argument self that is to say that the method/property belongs to that class. When I say:

metodo = função (def my_func():) ex: zero_list_maker

propriedade = variaveis de instancia ex: time line, which then within the methods we reference it like this: self.linha_do_tempo:

I assumed that each of the 100 tamanho_populacao shall store the result of each loop of the cycle:

import time
import random
import copy

class AG():

    cs = []
    gav = []                              
    icc = []
    lc = []
    oc = []
    pcal = []
    pc1 = []

    disciplinas = []

    primeiro_ano = []
    segundo_ano = []
    terceiro_ano = []
    quarto_ano = []

    linha_do_tempo = []
    TAM =  80

    def __init__(self):
        self.icc = ["A02", "A08"]
        self.lc = ["A09", "A10", "A11", "A12", "A13", "A01", "A02"]
        self.oc = ["A14", "A15", "A16", "A17", "A18", "A19", "A20", "A21", "A22", "A23", "A24", "A25", "A26", "A27", "A28", "A29", "A30", "A31", "A32", "A33", "A34", "A35", "A36", "A37", "A38", "A39", "A40", "A01", "A02", "A04", "A08"]
        self.pcal = ["A40", "A41", "A42", "A43", "A44", "A45", "A46", "A47", "A48", "A49", "A50", "A51", "A52", "A53", "A54", "A55", "A56", "A57", "A58", "A59", "A60", "A61", "A62", "A63", "A64", "A65", "A66", "A67", "A68", "A01", "A02", "A03", "A05", "A08"]
        self.pc1 = ["A69", "A70", "A71", "A72", "A73", "A74", "A01", "A02", "A08"]
        self.gav = ["A01", "A02", "A03", "A04", "A05", "A06", "A07", "A08"]

        self.primeiro_ano = [1101, 1102, 1103, 1104, 1105, 1106, 1107]
        self.segundo_ano = [2101, 2102, 2103, 2104, 2105, 2106, 2107, 2108]
        self.terceiro_ano = [3101, 3102, 3103, 3104, 3105, 3106, 3107, 3108]
        self.quarto_ano = [4101, 4102, 4103, 4104, 4105, 4106, 4107]

        _cs = 1101
        _gav = 1102
        _icc = 1103
        _lc = 1104
        _oc = 1105
        _pcal = 1106
        _pc1 = 1107

        self.disciplinas = [_cs, _gav, _icc, _lc, _oc, _pcal, _pc1]

        self.linha_do_tempo = self.zero_list_maker(self.TAM)
        print ("Inicializando a linha do tempo...")
        print ("Linha do tempo: ", self.linha_do_tempo)

    def zero_list_maker(self, length):
        listofzeros = [0] * length
        return listofzeros

    def gerar_populacao(self):    
        populacao = []
        tamanho_populacao = 100
        lCount = len(self.linha_do_tempo)
        while(tamanho_populacao > 0):
            # para nao alterar as listas originais fazemos um copy delas para cada individuo
            discis = copy.deepcopy(self.disciplinas)
            linha_tempo = copy.deepcopy(self.linha_do_tempo)
            randDisc = []
            positions = []
            for i in range(0, lCount-1):
                if(len(discis) > 0):
                    position = random.randint(0,lCount-2)
                    disc = random.choice(discis)
                    if(linha_tempo[position] == 0 and linha_tempo[position+1] == 0):
                        linha_tempo[position] = disc
                        linha_tempo[position+1] = disc
                        randDisc.append(disc)
                        discis.remove(disc)
                else:
                    break
            populacao.append(linha_tempo)
            tamanho_populacao -= 1
        return populacao


ag = AG()
populacao = ag.gerar_populacao()
print(populacao)
primeiro_individuo = populacao[0]
print('\n\n\nPrimeira pessoa:\n', primeiro_individuo)

I deleted some Imports I wasn’t using and the comments for the code didn’t get too extensive here.

  • Perfect even Miguel! That’s exactly what it is! The only thing I was thinking about is this: now that I’ve gone to see that actually during initialization, notice that when the disciplines are distributed in the Time line (which was initialized with zeros), the disciplines are placed in the first positions of the Time line. In fact the disciplines should be distributed exactly as they are, but in random positions of the time_line.

  • Haa yes got it, I’ll edit @Allan

  • Done @Allan on top

  • I don’t know if I could explain it properly, eh that my net stopped working here:

  • now that I saw haha that same, well that I was talking about ;-) in the distribution of individuals is mandatory to stay one after the other, for example:

  • It has to look like this: [0, 0, 0, 0, 0, 1102, 1102, 0, 0, 0, 0, 0, 0, 1107, 1107, 0, 1103, 1103, 1103, 0, 0, 0, 0, 1105, 1105, 0, 0, 0, 0, 1106, 1106, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

  • Instead of being like this: [0, 0, 0, 0, 0, 1102, 0, 0, 0, 0, 0, 0, 0, 0, 1107, 0, 0, 0, 1103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1106, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

  • Because it’s a school schedule, so the subjects are distributed one after the other. The vector index represents 50 min each lesson lasts =)

  • I now did the following, to make it easier to visualize, I created code for the disciplines, I will change the code for you to take a look ;-)

  • I changed, it is there in the question! The only thing that has changed is that I created a code for each discipline: _Cs = 1101 and so on. The vector of disciplines was thus: disciplines = [_Cs, _Gav, _icc, _Lc, _oc, _Pcal, _pc1]

  • Here: http://chat.stackexchange.com/rooms/41402/discussion-between-miguel-and-allan

  • 1

    Be careful you two with one thing - Python should not declare lists in the body of a box: the same list will be shared by all instances of the class. If each instance of the class must have its own collections, they must be initialized within the method __init__.

  • 1

    It’s true, I’m already working on optimizing it. Obgado @jsbueno

Show 8 more comments

Browser other questions tagged

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