Shorten Object Method Call

Asked

Viewed 60 times

0

Recently I was doing college exercises, we’re seeing inheritance, and I made a code that generated many lines to demonstrate that class inheritance is working, there’s some way to shorten those calls at the end of the program?

atleta1 = Atleta('Atleta', 'Não', 78)
atleta1.imprime()
atleta1.aposentar()
atleta1.aquecer()

corredor1 = Corredor('Corredor', 'Não', 66)
corredor1.imprime()
corredor1.aposentar()
corredor1.aquecer()
corredor1.correr()

nadador1 = Nadador('Nadador', 'Sim', 70)
nadador1.imprime()
nadador1.aposentar()
nadador1.aquecer()
nadador1.nadar()

ciclista1 = Ciclista('Ciclista', 'Sim', 76)
ciclista1.imprime()
ciclista1.aposentar()
ciclista1.aquecer()
ciclista1.pedalar()

triatleta1 = TriAtleta('TriAtleta', 'Não', 65)
triatleta1.imprime()
triatleta1.aposentar()
triatleta1.aquecer()
triatleta1.correr()
triatleta1.nadar()
triatleta1.pedalar()

3 answers

1

Well, I created some classes to explain some important concepts.

The Athlete class is the base where you will have the attributes and the common methods in all other classes.

class Atleta:
    def __init__(self, tipo, aposentado, idade):
        self.tipo = tipo
        self.aposentado = aposentado
        self.idade = idade

    def imprime(self):
        print(f'Tipo: {self.tipo} | Aposentado: {self.aposentado} | Idade: {self.idade}')

    def aposentar(self):
        if self.aposentado == 'Não':
            if self.idade >= 65:
                self.aposentado = 'Sim'
                print(f'{self.tipo} de {self.idade} anos acabou de se aposentar!')
            else:
                print(f'{self.tipo} de {self.idade} anos ainda não tá na hora de se aposentar!')
        else:
            print(f'{self.tipo} de {self.idade} anos já é aposentado!')

    def aquecer(self):
        print(f'{self.tipo} de {self.idade} anos está aquecendo!')

Therefore, to create another custom class, it is passed as inheritance the class Atleta and inherited methods and attributes, leaving only to declare the method responsible for this type of Athlete.

class Corredor(Atleta):
    def __init__(self, tipo, aposentado, idade):
        super(Corredor, self).__init__(tipo, aposentado, idade)

    def correr(self):
        print(f'{self.tipo} de {self.idade} anos está correndo!')

class Nadador(Atleta):
    def __init__(self, tipo, aposentado, idade):
        super(Nadador, self).__init__(tipo, aposentado, idade)

    def nadar(self):
        print(f'{self.tipo} de {self.idade} anos está nadando!')

class Ciclista(Atleta):
    def __init__(self, tipo, aposentado, idade):
        super(Ciclista, self).__init__(tipo, aposentado, idade)

    def pedalar(self):
        print(f'{self.tipo} de {self.idade} anos está pedalando!')

It is possible to notice that Triathlete inherits the other 3 classes, so it is possible to pass to this class the unique methods of every class, that is code reuse!

class TriAtleta(Corredor, Nadador, Ciclista):
    def __init__(self, tipo, aposentado, idade):
        super(TriAtleta, self).__init__(tipo, aposentado, idade)

Here a dictionary is created with the appropriate actions like string of each type of class, that is, if you pass an Athlete as a parameter, it is returned ['prints', 'retire', 'warm up'].

acoes = {
    'Atleta': ['imprime', 'aposentar', 'aquecer'],
    'Corredor': ['imprime', 'aposentar', 'aquecer', 'correr'],
    'Nadador': ['imprime', 'aposentar', 'aquecer', 'nadar'],
    'Ciclista': ['imprime', 'aposentar', 'aquecer', 'pedalar'],
    'TriAtleta': ['imprime', 'aposentar', 'aquecer', 'correr', 'nadar', 'pedalar'],
}

Here are Instantiated the Classes generating the Object of each type of athlete.

atleta = Atleta('Atleta', 'Não', 78)
corredor = Corredor('Corredor', 'Não', 66)
nadador = Nadador('Nadador', 'Sim', 70)
ciclista = Ciclista('Ciclista', 'Sim', 76)
triatleta = TriAtleta('TriAtleta', 'Não', 65)

As @epx well commented, it is possible to traverse a loop for each athlete and the other loop is for each action of that particular athlete. The getattr method calls the function with the name of each action of the current athlete, if it does not find the method, it returns a function that returns an empty string. That is polymorphism.

for pessoa in [atleta, corredor, nadador, ciclista, triatleta]:
    for acao in acoes[pessoa.tipo]:
        getattr(pessoa, acao, lambda: '')()

References

https://wiki.python.org.br/ProgramacaoOrientadaObjetoPython

1

A less repetitive way of verifying that classes have exactly inherited these methods is to use the function hasattr on each object.

acoes = ['imprime', 'aposentar', 'aquecer', 'correr', 'nadar', 'pedalar']

for pessoa in [atleta, corredor, nadador, ciclista, triatleta]:
    print(f'Objeto da classe: {type(pessoa)}')

    for acao in acoes:
        if hasattr(pessoa, acao):
            print(f'Possui o método {acao}')
        else:
            print(f'Não possui o método {acao}')

    print()

Or, if you want to dynamically verify all methods of a given object, use the dir.

for pessoa in [atleta, corredor, nadador, ciclista, triatleta]:
    print(f'Lista de métodos do objeto da classe: {type(pessoa)}')

    for atributo in dir(pessoa):
        if not atributo.startswith('__') and callable(getattr(pessoa, atributo)):
            print(atributo)

    print()

Note that you need to check that the attribute does not start with __ (because they are the reserved attributes created by Python itself) and if the attribute is called (to only print methods, not properties).

0

Shorten how? One possibility is to loop a list to content the objects and call the common methods that everyone has, something like

for atleta in [atleta1, corredor1, nadador1, ...]:
    atleta.imprime()
    atleta.aposentar()
    ...

Another thing you can do is arrange for all calls to return self, then you could chain horizontally:

atleta1.imprime().aposentar().aquecer()...

Browser other questions tagged

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