Python3 Orientado a Objetos

Python ha sido un lenguaje orientado a objetos desde su diseño inicial; por eso, crear una clase y un objeto en Python es muy fácil. En este capítulo presentaremos en detalle la programación orientada a objetos de Python.

Si antes no has tenido contacto con lenguajes de programación orientados a objetos, quizás necesites comprender primero algunas características básicas de estos lenguajes y formarte un concepto fundamental de orientación a objetos, lo que te ayudará a aprender más fácilmente la programación orientada a objetos de Python.

A continuación, echemos un vistazo breve a algunas características básicas de la orientación a objetos.


Introducción a la tecnología orientada a objetos

  • Clase (Class):Se utiliza para describir un conjunto de objetos que tienen los mismos atributos y métodos. Define los atributos y métodos comunes a cada objeto de ese conjunto. Un objeto es una instancia de la clase.
  • Método:Función definida en la clase.
  • Variable de clase:La variable de clase es compartida por todos los objetos instanciados. Se define dentro de la clase y fuera del cuerpo de la función. Por lo general, la variable de clase no se utiliza como variable de instancia.
  • Miembro de datos:Las variables de clase o variables de instancia se utilizan para manejar los datos relacionados con la clase y sus objetos de instancia.
  • Anulación de métodos (override):Si un método heredado de la clase padre no satisface las necesidades de la subclase, se puede reescribir. Este proceso se llama anulación (override) del método, también conocido como reescritura del método.
  • Variable local:Variable definida en un método; solo actúa sobre la instancia actual de la clase.
  • Variable de instancia:En la declaración de la clase, los atributos se representan mediante variables. Estas variables se denominan variables de instancia; una variable de instancia es una variable modificada con self.
  • Herencia:Es decir, una clase derivada (derived class) hereda los campos y métodos de la clase base (base class). La herencia también permite tratar un objeto de una clase derivada como un objeto de la clase base. Por ejemplo, en un diseño así: un objeto de tipo Dog deriva de la clase Animal, lo que simula una relación "es un" (is-a) (por ejemplo, Dog es un Animal).
  • Instanciación:Crear una instancia de una clase, es decir, el objeto concreto de la clase.
  • Objeto:Instancia de una estructura de datos definida mediante una clase. El objeto incluye dos miembros de datos (variable de clase y variable de instancia) y métodos.

En comparación con otros lenguajes de programación, Python añade el mecanismo de clases sin añadir nueva sintaxis ni semántica en la medida de lo posible.

Las clases en Python proporcionan todas las funciones básicas de la programación orientada a objetos: el mecanismo de herencia de clases permite múltiples clases base; la clase derivada puede anular cualquier método de la clase base; y los métodos pueden llamar a métodos del mismo nombre en la clase base.

Un objeto puede contener cualquier cantidad y tipo de datos.

Definición de clase

La sintaxis es la siguiente:

class ClassName: <statement-1> . . . <statement-N>

Después de instanciar la clase, se pueden usar sus atributos. En realidad, después de crear una clase, se puede acceder a sus atributos a través del nombre de la clase.

Objeto de clase

El objeto de clase admite dos operaciones: referencia a atributos e instanciación.

La referencia a atributos utiliza la misma sintaxis estándar que todas las referencias a atributos en Python:obj.name。

Una vez creado el objeto de clase, todos los nombres en el espacio de nombres de la clase son nombres de atributos válidos. Así que si la definición de clase es así:

Ejemplo (Python 3.0+)

#!/usr/bin/python3 class MyClass: """Un ejemplo simple de clase""" i = 12345 def f(self): return 'hello world' # Instanciar la clase x = MyClass() # Acceder a los atributos y métodos de la clase print("El atributo i de la clase MyClass es:", x.i) print("El método f de la clase MyClass imprime:", x.f())

Lo anterior crea una nueva instancia de la clase y asigna ese objeto a la variable local x, siendo x un objeto vacío.

Al ejecutar el programa anterior, el resultado es:

MyClass 类的属性 i 为: 12345
MyClass 类的方法 f 输出为: hello world

La clase tiene un método especial llamado __init__() (método constructor), que se llama automáticamente al instanciar la clase, como se muestra a continuación:

def __init__(self): self.data = []

Si la clase define el método __init__(), la operación de instanciación llamará automáticamente al método __init__(). Al instanciar la clase MyClass como se muestra a continuación, se llamará al método __init__() correspondiente:

x = MyClass()

Por supuesto, el método __init__() puede tener parámetros; los parámetros se pasan a la operación de instanciación de la clase a través de __init__(). Por ejemplo:

Ejemplo (Python 3.0+)

#!/usr/bin/python3 class Complex: def __init__(self, realpart, imagpart): self.r = realpart self.i = imagpart x = Complex(3.0, -4.5) print(x.r, x.i) # Resultado: 3.0 -4.5

self representa la instancia de la clase, no la clase

Los métodos de una clase tienen una única diferencia especial con las funciones normales: deben tener unprimer parámetro adicional, que por convención se llama self.

class Test: def prt(self): print(self) print(self.__class__) t = Test() t.prt()

El resultado de ejecutar el ejemplo anterior es:

<__main__.Test instance at 0x100771878>
__main__.Test

En el resultado de la ejecución se puede ver claramente que self representa la instancia de la clase, es decir, la dirección del objeto actual, mientras que self.class apunta a la clase.

self no es una palabra clave de Python; podemos cambiarla por ejemplo y también se ejecutará correctamente:

class Test: def prt(ejemplo): print(ejemplo) print(ejemplo.__class__) t = Test() t.prt()

El resultado de ejecutar el ejemplo anterior es:

<__main__.Test instance at 0x100771878>
__main__.Test

En Python, self es un nombre convencional que se utiliza para representar la propia instancia (objeto) de la clase. Es una referencia a la instancia que permite que los métodos de la clase accedan y manipulen los atributos de la instancia.

Cuando defines una clase y defines métodos dentro de ella, el primer parámetro suele llamarse self. Aunque puedes usar otro nombre, se recomienda encarecidamente usar self para mantener la consistencia y legibilidad del código.

Ejemplo

class MyClass:
    def __init__(self, value):
        self.value = value

    def display_value(self):
        print(self.value)

# Crear una instancia de la clase
obj = MyClass(42)

# Llamar al método de la instancia
obj.display_value() # Salida: 42

En el ejemplo anterior, self es una referencia que apunta a la instancia de la clase; se usa__init__en el constructor para inicializar los atributos de la instancia, y tambiéndisplay_valueen los métodos para acceder a los atributos de la instancia. Usando self, puedes acceder y manipular los atributos de la instancia dentro de los métodos de la clase, logrando así el comportamiento de la clase.


Métodos de la clase

Dentro de la clase, se usa ladefpalabra clave para definir un método. A diferencia de la definición de funciones normales, el método de clase debe incluir el parámetro self, y debe ser el primer parámetro; self representa la instancia de la clase.

Ejemplo (Python 3.0+)

#!/usr/bin/python3 # Definición de clase class people: # Definir atributos básicos name = '' age = 0 # Definir atributos privados; los atributos privados no se pueden acceder directamente desde fuera de la clase __weight = 0 # Definir el método constructor def __init__(self,n,a,w): self.name = n self.age = a self.__weight = w def speak(self): print("%s dice: tengo %d años." %(self.name,self.age)) # Instanciar la clase p = people('ejemplo',10,30) p.speak()

Al ejecutar el programa anterior, el resultado es:

ejemplo 说: 我 10 岁。

Herencia

Python también admite la herencia de clases. Si un lenguaje no soporta la herencia, las clases no tienen mucho sentido. La definición de una clase derivada es la siguiente:

class DerivedClassName(BaseClassName): <statement-1> . . . <statement-N>

La subclase (clase derivada DerivedClassName) hereda los atributos y métodos de la clase padre (clase base BaseClassName).

BaseClassName (en el ejemplo, el nombre de la clase base) debe estar en el mismo ámbito que la definición de la clase derivada. Además de una clase, también se puede usar una expresión; esto es muy útil cuando la clase base está definida en otro módulo:

class DerivedClassName(modname.BaseClassName):

Ejemplo (Python 3.0+)

#!/usr/bin/python3 # Definición de clase class people: # Definir atributos básicos name = '' age = 0 # Definir atributos privados; los atributos privados no se pueden acceder directamente desde fuera de la clase __weight = 0 # Definir el método constructor def __init__(self,n,a,w): self.name = n self.age = a self.__weight = w def speak(self): print("%s dice: tengo %d años." %(self.name,self.age)) # Ejemplo de herencia simple class student(people): grade = '' def __init__(self,n,a,w,g): # Llamar al constructor de la clase padre people.__init__(self,n,a,w) self.grade = g # Anular el método de la clase padre def speak(self): print("%s dice: tengo %d años, estoy en el grado %d"%(self.name,self.age,self.grade)) s = student('ken',10,60,3) s.speak()

Al ejecutar el programa anterior, el resultado es:

ken 说: 我 10 岁了,我在读 3 年级

Herencia múltiple

Python también admite de forma limitada la herencia múltiple. La definición de una clase con herencia múltiple tiene la forma del siguiente ejemplo:

class DerivedClassName(Base1, Base2, Base3): <statement-1> . . . <statement-N>

Hay que prestar atención al orden de las clases padre entre paréntesis; si las clases padre tienen métodos con el mismo nombre y no se especifica cuál usar en la subclase, Python busca de izquierda a derecha. Es decir, cuando el método no se encuentra en la subclase, se busca de izquierda a derecha si las clases padre contienen el método.

Ejemplo (Python 3.0+)

#!/usr/bin/python3 # Definición de clase class people: # Definir atributos básicos name = '' age = 0 # Definir atributo privado; el atributo privado no se puede acceder directamente desde fuera de la clase __weight = 0 # Definir método constructor def __init__(self,n,a,w): self.name = n self.age = a self.__weight = w def speak(self): print("%s dice: tengo %d años." %(self.name,self.age)) # Ejemplo de herencia única class student(people): grade = '' def __init__(self,n,a,w,g): # Llamar al constructor de la clase padre people.__init__(self,n,a,w) self.grade = g # Sobrescribir el método de la clase padre def speak(self): print("%s dice: tengo %d años y estoy en el grado %d"%(self.name,self.age,self.grade)) # Otra clase, preparación antes de la herencia múltiple class speaker(): topic = '' name = '' def __init__(self,n,t): self.name = n self.topic = t def speak(self): print("Me llamo %s, soy un orador y el tema de mi discurso es %s"%(self.name,self.topic)) # Herencia múltiple class sample(speaker,student): a ='' def __init__(self,n,a,w,g,t): student.__init__(self,n,a,w,g) speaker.__init__(self,n,t) test = sample("Tim",25,80,4,"Python") test.speak() # Si el nombre del método es el mismo, por defecto se llama al método de la clase padre que aparece primero entre paréntesis

La salida del programa anterior es:

我叫 Tim,我是一个演说家,我演讲的主题是 Python

Anulación de métodos

Si la funcionalidad del método de tu clase padre no satisface tus necesidades, puedes sobrescribir el método de la clase padre en la subclase. Ejemplo:

Ejemplo (Python 3.0+)

#!/usr/bin/python3 class Parent: # Definir la clase padre def myMethod(self): print ('Llamar al método de la clase padre') class Child(Parent): # Definir la subclase def myMethod(self): print ('Llamar al método de la subclase') c = Child() # Instancia de la subclase c.myMethod() # La subclase llama al método sobrescrito super(Child,c).myMethod() # Usar un objeto de la subclase para llamar al método de la clase padre que ya ha sido sobrescrito

La función super()Se utiliza para llamar a un método de la clase padre (superclase).

La salida del programa anterior es:

Llamar al método de la subclase
Llamar al método de la clase padre

Más documentación:

Explicación de la subclase de Python que hereda el constructor de la clase padre


Atributos y métodos de la clase

Atributos privados de la clase

__private_attrs: Comienzan con dos guiones bajos. Declaran que el atributo es privado y no puede ser utilizado ni accedido directamente desde fuera de la clase. Cuando se usa dentro de los métodos de la claseself.__private_attrs。

Métodos de la clase

Dentro de una clase, se usa la palabra clave def para definir un método. A diferencia de la definición de funciones normales, el método de clase debe incluir un parámetroself, y debe ser el primer parámetro,selfRepresenta la instancia de la clase.

selfEl nombre no está fijado de forma obligatoria; también se puede usarthis, pero es mejor usarlo según la convención.self。

Métodos privados de la clase

__private_method: Comienzan con dos guiones bajos. Declaran que el método es privado y solo puede llamarse dentro de la clase, no desde fuera de la clase.self.__private_methods。

Ejemplo

Un ejemplo de atributos privados de la clase es el siguiente:

Ejemplo (Python 3.0+)

#!/usr/bin/python3 class JustCounter: __secretCount = 0 # Variable privada publicCount = 0 # Variable pública def count(self): self.__secretCount += 1 self.publicCount += 1 print (self.__secretCount) counter = JustCounter() counter.count() counter.count() print (counter.publicCount) print (counter.__secretCount) # Error, la instancia no puede acceder a la variable privada

La salida del programa anterior es:

1
2
2
Traceback (most recent call last):
  File "test.py", line 16, in <module>
    print (counter.__secretCount)  # 报错,实例不能访问私有变量
AttributeError: 'JustCounter' object has no attribute '__secretCount'

Un ejemplo de métodos privados de la clase es el siguiente:

Ejemplo (Python 3.0+)

#!/usr/bin/python3 class Site: def __init__(self, name, url): self.name = name # public self.__url = url # private def who(self): print('name : ', self.name) print('url : ', self.__url) def __foo(self): # Método privado print('Este es un método privado') def foo(self): # Método público print('Este es un método público') self.__foo() x = Site('Tutorial para novatos', 'www.example.com') x.who() # Salida normal x.foo() # Salida normal x.__foo() # Error

Resultado de la ejecución del ejemplo anterior:

Métodos especiales de la clase:

  • __init__ :Constructor, se llama al crear un objeto
  • __del__ :Destructor, se usa al liberar un objeto
  • __repr__ :Impresión, conversión
  • __setitem__ :Asignación por índice
  • __getitem__:Obtener valor por índice
  • __len__:Obtener longitud
  • __cmp__:Operación de comparación
  • __call__:Llamada de función
  • __add__:Operación de suma
  • __sub__:Operación de resta
  • __mul__:Operación de multiplicación
  • __truediv__:Operación de división
  • __mod__:Operación de módulo
  • __pow__:Potencia

Sobrecarga de operadores

Python también admite la sobrecarga de operadores. Podemos sobrecargar los métodos especiales de la clase. Ejemplo:

Ejemplo (Python 3.0+)

#!/usr/bin/python3 class Vector: def __init__(self, a, b): self.a = a self.b = b def __str__(self): return 'Vector (%d, %d)' % (self.a, self.b) def __add__(self,other): return Vector(self.a + other.a, self.b + other.b) v1 = Vector(2,10) v2 = Vector(5,-2) print (v1 + v2)

El resultado de ejecutar el código anterior es el siguiente:

Vector(7,8)
Otras extensiones