Pregunta 1¿Cuál de las siguientes es la forma correcta de definir una clase de Python?
Clases e instancias — Definir tu propio tipo
Aprende las clases e instancias de Python desde cero. Recorre las definiciones de class, el papel de self y el uso de __init__ para establecer atributos, todo con diagramas.
Como ya mencionamos en el resumen anterior, los tipos integrados como int, str, list y dict no pueden representar directamente conceptos de negocio como "usuario", "producto" o "pedido". El siguiente paso es definir tu propio tipo con class: ese es el punto de entrada a la programación orientada a objetos (POO).
¿Por qué programación orientada a objetos?
Todo lo que has escrito hasta ahora es procedimental: combinar funciones para impulsar el comportamiento. A medida que los programas crecen, los datos relacionados y la lógica que opera sobre ellos tienden a dispersarse, y los cambios y la reutilización se vuelven más difíciles.
Con la programación orientada a objetos (POO) agrupas los datos relacionados (atributos) y las operaciones sobre ellos (métodos) en una única unidad: un objeto. Eso te permite dar forma a tu código en torno a conceptos del mundo real.
function(data). La POO pone ambos dentro de un objeto para que vivan juntos.Una clase es un plano, una instancia es la cosa real
Dos términos anclan todo en POO:
- Clase: un plano que enumera los atributos y métodos que tendrás
- Instancia: la cosa real construida a partir de ese plano
Por ejemplo, define una clase Product para capturar el concepto de producto y podrás crear tantas instancias individuales de productos —apple, banana, orange— como necesites. Juntas, las clases y las instancias se denominan objetos.
Definir una clase mínima
Vamos a definir realmente una clase Product para los artículos de una tienda. La sintaxis es class NombreDeClase:. Por convención, los nombres de clase en Python usan CapitalizedCamelCase (Product, UserAccount, etc.).
Una variable escrita directamente dentro de la clase, como name = "apple", se trata como un valor por defecto que la clase contiene, y puedes leerla a través del nombre de la clase como Product.name.
class Product:
name = "apple"
price = 150
# Acceder directamente a la clase
print(Product.name) # apple
print(Product.price) # 150
class —name / price— se adhieren a la propia clase y se pueden leer directamente a través del nombre de la clase como Product.name.Las variables escritas directamente bajo class se llaman variables de clase. Se comportan de forma diferente a las variables de instancia (que cada instancia posee por separado), pero volveremos a esa distinción en un artículo posterior. Por ahora, lo único que necesitas es la idea mínima: "adhiere un valor a la propia clase y luego léelo como Product.name".
Usa __init__ para dar a cada instancia sus propios valores
La clase mínima anterior solo adhirió un valor fijo como name = "apple" a la clase, así que cada instancia que construyas sería "apple". En código real quieres múltiples instancias a partir de una sola clase —apple, banana, orange— cada una con sus propios valores.
La herramienta para esto es el método especial de Python __init__, también conocido como constructor o inicializador. Cuando llamas a Product("apple", 150) con argumentos, Python llama automáticamente a __init__, y dentro de él escribes self.name = name para almacenar valores en la propia instancia.
Doble guión bajo — Una convención de Python
Los nombres envueltos en doble guión bajo como __init__ se llaman métodos dunder. Python les da un significado especial y los llama automáticamente en ciertos momentos: __init__ cuando se crea una instancia, __str__ cuando se imprime algo, etc. Cubriremos __init__ con más profundidad y conoceremos __del__ en el próximo artículo.
Product("apple", 150) hace que Python ① prepare una instancia vacía, ② la pase a __init__ como self, y ③ escriba los argumentos en los atributos de esa instancia, dejándote con un objeto terminado.class Product:
def __init__(self, name, price): # Llamado automáticamente al crear una instancia
self.name = name
self.price = price
apple = Product("apple", 150)
banana = Product("banana", 80)
print(apple.name, apple.price) # apple 150
print(banana.name, banana.price) # banana 80
# apple y banana son objetos diferentes
print(apple is banana) # False
Product(...) crea un objeto separado. apple, banana y orange provienen del mismo plano pero son objetos diferentes, cada uno con su propio name / price.Cómo funcionan los métodos y self
Los atributos por sí solos solo "contienen datos": no muy diferente de un dict simple. El verdadero objetivo de la POO es que también puedes escribir operaciones sobre la instancia junto con los datos. Esas operaciones se llaman métodos.
def es un método. El primer parámetro self es obligatorio, y en cada llamada Python lo rellena con la instancia desde la que se llamó al método. Dentro del método, escribe self.name para acceder a los atributos de esa instancia.Cuando escribes apple.show(), internamente Python ejecuta Product.show(apple): self acaba conteniendo apple.
- apple y banana son instancias separadas
- Cuando llamas a
apple.show()…
- self se rellena con apple automáticamente
self.namelee apple.name- Para
banana.show(),selfse convierte enbanana
show, llamar desde apple lee el name de apple, llamar desde banana lee el de banana.class Product:
def __init__(self, name, price):
self.name = name
self.price = price
def show(self): # El primer parámetro siempre es self
print(f"{self.name}: ${self.price}")
apple = Product("apple", 150)
banana = Product("banana", 80)
apple.show() # apple: $150 internamente igual que Product.show(apple)
banana.show() # banana: $80 internamente igual que Product.show(banana)
apple.show() pone apple en self, mientras que llamar a banana.show() pone banana en self. El mismo método show se ejecuta con un self diferente cada vez, según quien lo llame.self es solo una convención
Sintácticamente, el primer parámetro puede ser cualquier cosa: def show(this): también funciona. Pero casi todas las bases de código de Python usan self, así que cíñete a ello. Cualquier otra cosa despista a los lectores.
En este artículo aprendiste los fundamentos de la programación orientada a objetos. Cubriremos las variables y los métodos con más profundidad en artículos posteriores.
Verificación de conocimientos
Responde cada pregunta una a una.
Pregunta 2¿Qué se pasa automáticamente al primer parámetro self de un método cuando se le llama?
Pregunta 3¿Qué imprime el siguiente código?class P: def __init__(self, x): self.x = xa = P(10)b = P(20)print(a.x + b.x)