# Clases y Objetos

## <mark style="color:blue;">Trabajando con Clases y Objetos</mark>

### 1. Definiendo una clase

```python
class Coche():
    """Esta clase representa a un coche"""
    
    def __init__(self, modelo, potencia, consumo):
        """Inicializa los atributos de instancia
        Argumentos posicionales:
        modelo -- str que representa el modelo del coche
        potencia -- int que representa la potencia en cv
        consumo -- int que presententa el consumo en l/100km
        """
        self.modelo = modelo
        self.potencia = potencia
        self.consumo = consumo
        
    def especificaciones(self):
        """Muestra las especificaciones del coche"""
        print("Modelo: ", self.modelo,
             "\nPotencia: {} cv".format(self.potencia),
             "\nConsumo: {} l/100km".format(self.consumo),
             )
```

```python
help(Coche)
Help on class Coche in module __main__:

class Coche(builtins.object)
 |  Coche(modelo, potencia, consumo)
 |  
 |  Esta clase representa a un coche
 |  
 |  Methods defined here:
 |  
 |  __init__(self, modelo, potencia, consumo)
 |      Inicializa los atributos de instancia
 |      
 |      Argumentos posicionales:
 |      modelo -- str que representa el modelo del coche
 |      potencia -- int que representa la potencia en cv
 |      consumo -- int que presententa el consumo en l/100km
 |  
 |  especificaciones(self)
 |      Muestra las especificaciones del coche
 |  
 |  ----------------------------------------------------------------------
 |  Data descriptors defined here:
 |  
 |  __dict__
 |      dictionary for instance variables (if defined)
 |  
 |  __weakref__
 |      list of weak references to the object (if defined)
```

```python
mercedes = Coche("Mercedes c200", 180, 7)

mercedes.especificaciones()

Modelo:  Mercedes c200 
Potencia: 180 cv 
Consumo: 7 l/100km
```

### 2. Atributos con valores por defecto

```python
class Coche():
    """Esta clase representa a un coche"""
    
    def __init__(self, modelo, potencia, consumo):
        """Inicializa los atributos de instancia
        Argumentos posicionales:
        modelo -- str que representa el modelo del coche
        potencia -- int que representa la potencia en cv
        consumo -- int que presententa el consumo en l/100km
        """
        self.modelo = modelo
        self.potencia = potencia
        self.consumo = consumo
        self.km_actuales = 0 # Valor por defecto
        
    def especificaciones(self):
        """Muestra las especificaciones del coche"""
        print("Modelo: ", self.modelo,
             "\nPotencia: {} cv".format(self.potencia),
             "\nConsumo: {} l/100km".format(self.consumo),
              "\nKilometros Actuales: ", self.km_actuales
             )
```

```python
mercedes = Coche("Mercedes c200", 180, 7)

mercedes.especificaciones()

Modelo:  Mercedes c200 
Potencia: 180 cv 
Consumo: 7 l/100km 
Kilometros Actuales:  0
```

### 3. Modificando los valores de los atributos de un objeto

La manera más sencilla de modificar el valor de un atributo de un objeto es utilizando la sintaxis:

```python
<objeto>.<atributo> = <nuevo_valor>
```

```python
mercedes.km_actuales = 200

mercedes.especificaciones()

Modelo:  Mercedes c200 
Potencia: 180 cv 
Consumo: 7 l/100km 
Kilometros Actuales:  200
```

Por otro lado, existe una práctica mejor a la hora de modificar los atributos de la clase que consiste en hacerlo a través de un método especialmente creado para ello.

Esto nos permite realizar operaciones adicionales dentro de nuestro objeto siempre que se recibe un nuevo valor de un atributo.

{% code overflow="wrap" %}

```python
class Coche():
    """Esta clase representa a un coche""" 
    
    def __init__(self, modelo, potencia, consumo):
        """Inicializa los atributos de instancia
        Argumentos posicionales:
        modelo -- str que representa el modelo del coche
        potencia -- int que representa la potencia en cv
        consumo -- int que presententa el consumo en l/100km
        """
        self._modelo = modelo
        self._potencia = potencia
        self._consumo = consumo
        self._km_actuales = 0
        
    def especificaciones(self):
        """Muestra las especificaciones del coche"""
        print("Modelo: ", self._modelo,
             "\nPotencia: {} cv".format(self._potencia),
             "\nConsumo: {} l/100km".format(self._consumo),
              "\nKilometros Actuales: ", self._km_actuales
             )
             
    def actualizar_kilometros(self, kilometros):
        """Actualiza los kilometros del coche"""
        if kilometros > self._km_actuales:
            self._km_actuales = kilometros
        else:
            print("ERROR: No se puede establecer un número de kilometros inferior al actual")
```

{% endcode %}

```python
mercedes = Coche("Mercedes c200", 180, 7)

mercedes.especificaciones()
Modelo:  Mercedes c200 
Potencia: 180 cv 
Consumo: 7 l/100km 
Kilometros Actuales:  0

mercedes.actualizar_kilometros(1500)

mercedes.especificaciones()
Modelo:  Mercedes c200 
Potencia: 180 cv 
Consumo: 7 l/100km 
Kilometros Actuales:  1500

mercedes.actualizar_kilometros(500)
ERROR: No se puede establecer un número de kilometros inferior al actual
```

### 4. Extendiendo la funcionalidad de nuestra clase

{% code overflow="wrap" %}

```python
class Coche():
    """Esta clase representa a un coche"""
    
    def __init__(self, modelo, potencia, consumo):
        """Inicializa los atributos de instancia
        Argumentos posicionales:
        modelo -- str que representa el modelo del coche
        potencia -- int que representa la potencia en cv
        consumo -- int que presententa el consumo en l/100km
        """
        self._modelo = modelo
        self._potencia = potencia
        self._consumo = consumo
        self._km_actuales = 0
        
    def especificaciones(self):
        """Muestra las especificaciones del coche"""
        print("Modelo: ", self._modelo,
             "\nPotencia: {} cv".format(self._potencia),
             "\nConsumo: {} l/100km".format(self._consumo),
              "\nKilometros Actuales: ", self._km_actuales
             )
             
    def actualizar_kilometros(self, kilometros):
        """Actualiza los kilometros del coche"""
        if kilometros > self._km_actuales:
            self._km_actuales = kilometros
        else:
            print("ERROR: No se puede establecer un número de kilometros inferior al actual")
            
    def consumo_total(self):
        """Muestra el consumo total del coche desde el km 0"""
        consumo_total = (self._km_actuales / 100) * self._consumo
        print("El consumo total es de {} litros".format(consumo_total))
```

{% endcode %}

```python
mercedes = Coche("Mercedes c200", 180, 7)

mercedes.consumo_total()
El consumo total es de 0.0 litros

mercedes.actualizar_kilometros(100)

mercedes.consumo_total()
El consumo total es de 7.0 litros

mercedes.actualizar_kilometros(148_250)

mercedes.consumo_total()
El consumo total es de 10377.5 litros
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://afsh4ck.gitbook.io/desarrollo-con-python/orientacion-a-objetos/clases-y-objetos.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
