Question

I have this project for college and I'm running into a couple of errors in the test file provided by the teachers.

Most of them are related to this. For example, doing the following:

caminho(posicao(0,0)).caminho_junta_posicao('este').caminho_origem()

returns:

Traceback (most recent call last):
  File "<string>", line 1, in <fragment>
builtins.AttributeError: 'NoneType' object has no attribute 'caminho_origem'

However, doing this:

c1 = caminho(posicao(0,0))
c1.caminho_junta_posicao('este')
c1.caminho_origem()

doesn't return any errors but the intended position.

And I can't figure out why that happens. Bellow is the code defining both of the classes from the example, as my problem with others lies in very similar. Any help would really be appreciated. Thanks.

class posicao:
    def __init__(self,l,c):
        self.posicao=(l,c)
    def posicao_linha(self):
        return self.posicao[0]
    def posicao_coluna(self):
        return self.posicao[1]
    def posicao_igual(self,p2):
        return self.posicao[0] == p2.posicao_linha() and self.posicao[1]\
               == p2.posicao_coluna()
    def posicao_relativa(self,d):
        if d=='norte':
            return posicao(self.posicao_linha()-1,self.posicao_coluna())
        elif d=='sul':
            return posicao(self.posicao_linha()+1,self.posicao_coluna())
        elif d=='este':
            return posicao(self.posicao_linha(),self.posicao_coluna()+1)
        elif d=='oeste':
            return posicao(self.posicao_linha(),self.posicao_coluna()-1)




class caminho:
    def __init__(self,p):
        self.caminho = [p]
    def caminho_junta_posicao(self,d):
        p = self.caminho[-1]
        self.caminho = self.caminho + [p.posicao_relativa(d)]
    def caminho_origem(self):
        return self.caminho[0]
    def caminho_destino(self):
        return self.caminho[-1]
    def caminho_antes_destino(self):
        return self.caminho[:-1]
    def caminho_apos_origem(self):
        return self.caminho[1:]
    def caminho_comprimento(self):
        return len(self.caminho)
    def caminho_contem__ciclos(self):
        for p in range(len(self.caminho)):
            for p2 in self.caminho[p:]:
                if p2.posicao_igual(self.caminho[p]):
                    return True
        return False 
    def caminho_elimina_ciclos(self):
        caminho = self.caminho
        if self.caminho_contem_ciclos():
            for p in caminho:
                for p2 in caminho[caminho.index(p):]:
                    if p.posicoes_iguas(p2):
                        caminho = caminho[:index(p)]+caminho[index(p2):]
Was it helpful?

Solution

This method:

def caminho_junta_posicao(self,d):
    p = self.caminho[-1]
    self.caminho = self.caminho + [p.posicao_relativa(d)]

doesn't explicitly return anything, so the result of calling it is None. Therefore,

 caminho(posicao(0,0)).caminho_junta_posicao('este')

will give None, and None doesn't have a caminho_origem() method, hence your error.

Python convention is usually that methods which act in-place (like .append, .extend, and here your .caminho_junta_posicao) return None, which makes chaining like this impossible. On the other hand, it makes accidentally modifying the original object in a chain which you think is working on copies much harder. Sometimes chaining does come in handy, though (see the pandas library, for example, which makes extensive use of it to great benefit.)

I don't recommend doing this, but if you modified the method to return self at the end, i.e.

def caminho_junta_posicao(self,d):
    p = self.caminho[-1]
    self.caminho = self.caminho + [p.posicao_relativa(d)]
    return self

then the result of caminho(posicao(0,0)).caminho_junta_posicao('este') would be your (now-modified) caminho object, and you could chain it the way you tried.

OTHER TIPS

The code you expect to work (but doesn't) doesn't work because your method caminho_junta_posicao() doesn't explicitly return a value, which means it returns None, causing the error you're seeing.

The code which you stated did work (your second example), didn't actually work when I tried it (Python 3.1.3) -- I got the same error as before.

This is as expected, in that the behavior is consistent.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top