Solucionado (ver solução)
Solucionado
(ver solução)
4
respostas

[Dúvida] Preciso de uma resposta que não seja feita por recurso de IA, por favor.

Obs.: tive de refazer a pergunta pois foi respondida anteriormente com recurso de IA. Como a resposta estava errada e sei que tópicos que já possuem respostas não são mais visualizados, estou postando mais uma vez.

Escrevi o seguinte código para limitar os tipos de moto que poderiam ser inseridos a 2:

from ex.vehicle.modules.vehicle import Vehicle


class Bike(Vehicle):
    def __init__(self, model, brand, bike_type):
        super().__init__(model, brand)
        self._bike_type = bike_type

    def __str__(self):
        return ( 
            f"{super().__str__()}" \
            f"Bike type: {self.bike_type}\n"
        )

    @property
    def bike_type(self):
        return self._bike_type
    
    @bike_type.setter
    def bike_type(self, type):
        if type.lower() == "sporty" or type.lower() == "casual":
            self._bike_type = type
        else:
            print("The type of bike can be just 'casual' or 'sporty'.")

.

Problema: por alguma motivo, quando eu crio uma instância da classe, tal como:

bike = Bike(
    model="Hornet 2000",
    brand="Honda",
    bike_type="anything",
)

O parâmetro "bike_type" é aceito (mesmo que não seja permitido pelo meu setter). Aparentemente, isso ocorre pois quando estamos criando um objeto, o mesmo atribui os valores diretamente aos atributos sem antes passar pelo setter.

.

Não consigo entender por que isso foi criado dessa forma. Gostaria de saber como contornar esse comportamento estranho do Python ou se, na verdade, estou cometendo algum erro na minha escrita.

4 respostas

Olá!

O que está acontecendo é que o seu setter está sendo sobrescrito pelo construtor da classe Bike, porque no momento da criação da instância o valor de bike_type está sendo recebido direto pelo construtor.

Nesse caso, se você quer manter a criação dessa propriedade junto com a criação de cada instância de Bike, pode colocar a chamada da validação, que atualmente está dentro do setter, dentro do construtor, como uma função validadora à parte.

Espero ter ajudado! Bons estudos :)

Não consegui visualizar como se faz isso.

Seria algo assim?

from ex.vehicle.modules.vehicle import Vehicle


class Bike(Vehicle):
    def __init__(self, model, brand, bike_type):
        super().__init__(model, brand)
        self._bike_type = None
        self.bike_type = bike_type

    def __str__(self):
        return ( 
            f"{super().__str__()}" \
            f"Bike type: {self.bike_type}\n"
        )

    @property
    def bike_type(self):
        return self._bike_type
    
    @bike_type.setter
    def bike_type(self, type):
        if type.lower() == "sporty" or type.lower() == "casual":
            self._bike_type = type
        else:
            print("The type of bike can be just 'casual' or 'sporty'.")

.

Pelo que entendi da sua descrição, teria de fazer assim para conseguir manter o atributo protected/private.

solução!

Olá!

Sim, é quase isso :) Duas coisas que podem ser melhoradas nesse caso:

  1. No exemplo abaixo retiramos a linha que fazia o "set" do valor como nulo antes de associar o valor, pois não é necessária;
  2. também adicionamos uma exceção. Assim, ao se tentar criar uma instância com um valor não permitido para bike_type, é retornado um erro, assim o objeto não retorna como nulo. Sem a exceção, o objeto era criado sem valor nenhum se seu valor fosse inválido e o erro só apareceria mais para a frente, ao tentar "imprimir" o objeto com print.

Exemplo:

from ex.vehicle.modules.vehicle import Vehicle


class Bike(Vehicle):
    def __init__(self, model, brand, bike_type):
        super().__init__(model, brand)
        self.bike_type = bike_type

    def __str__(self):
        return (
            f"{super().__str__()}" 
            f"Bike type: {self.bike_type}\n"
        )

    @property
    def bike_type(self):
        return self._bike_type

    @bike_type.setter
    def bike_type(self, type):
        if type.lower() == "sporty" or type.lower() == "casual":
            self._bike_type = type
        else:
            print("The type of bike can be just 'casual' or 'sporty'.")
            raise Exception( "Message Error") 

Espero ter ajudado!

Bons estudos ;)

Consegui entender, obrigado!