Python Orientado a Objetos
Python ha sido un lenguaje orientado a objetos desde su diseño. 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 no has tenido contacto previo con lenguajes de programación orientados a objetos, quizás necesites conocer primero algunas características básicas de estos lenguajes y formar un concepto básico de orientación a objetos en tu mente, lo que te ayudará a aprender más fácilmente la programación orientada a objetos de Python.
A continuación, primero veamos brevemente algunas características básicas de la orientación a objetos.
Introducción a la tecnología orientada a objetos
- Clase:Se usa para describir una colección de objetos que tienen los mismos atributos y métodos. Define los atributos y métodos comunes a cada objeto de esa colección. Un objeto es una instancia de 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 las funciones. Normalmente no se usa como variable de instancia.
- Miembro de datos:Variable de clase o variable de instancia, utilizada para manejar datos relacionados con la clase y sus objetos de instancia.
- Sobrescritura de métodos:Si el método heredado de la clase padre no satisface las necesidades de la subclase, se puede reescribir. Este proceso se llama anulación (override) de método, también conocido como sobrescritura de método.
- Variable local:Variable definida en un método, que solo actúa sobre la instancia actual de la clase.
- Variable de instancia:En la declaración de la clase, los atributos se representan con variables. Esta variable se denomina variable de instancia, y se declara dentro de la declaración de la clase pero fuera de los demás métodos miembros de la clase.
- Herencia:Es decir, una clase derivada hereda los campos y métodos de la clase base. La herencia también permite tratar un objeto de una clase derivada como un objeto de la clase base. Por ejemplo, hay un diseño así: un objeto de tipo Dog deriva de la clase Animal, lo que simula una relación "es un" (is-a) (ejemplo en la figura: Dog es un Animal).
- Instanciación:Crear una instancia de una clase, es decir, el objeto concreto de la clase.
- Método:Función definida en la clase.
- Objeto:Instancia de una estructura de datos definida por la clase. Un objeto incluye dos miembros de datos (variable de clase y variable de instancia) y métodos.
Crear una clase
Usa la declaración `class` para crear una nueva clase. Después de `class` va el nombre de la clase y termina con dos puntos:
class ClassName: '类的帮助信息' #类文档字符串 class_suite #类体
La información de ayuda de la clase se puede consultar mediante `ClassName.__doc__`.
`class_suite` se compone de miembros de la clase, métodos y atributos de datos.
Ejemplo
El siguiente es un ejemplo simple de una clase en Python:
Ejemplo
La variable `empCount` es una variable de clase; su valor se compartirá entre todas las instancias de esta clase. Puedes acceder a ella usando `Employee.empCount` dentro de la clase o desde fuera de la clase.
El primer método, `__init__()`, es un método especial, llamado constructor o método de inicialización de la clase. Se llama cuando se crea una instancia de esta clase.
`self` representa la instancia de la clase. `self` es obligatorio al definir métodos de la clase, aunque no es necesario pasar el parámetro correspondiente al llamar al método.
`self` representa la instancia de la clase, no la clase.
Los métodos de una clase solo tienen una diferencia especial con las funciones ordinarias: deben tener un parámetro adicionalcomo nombre del primer parámetro,según la convención, su nombre es `self`.
El resultado de ejecutar el ejemplo anterior es:
<__main__.Test instance at 0x10d066878> __main__.Test
Del resultado de ejecución se puede ver claramente que `self` representa la instancia de la clase, representa la dirección del objeto actual, mientras queself.__class__apunta a la clase.
`self` no es una palabra clave de Python; si lo reemplazamos por `ejemplo`, también se ejecutará correctamente:
Ejemplo
El resultado de ejecutar el ejemplo anterior es:
<__main__.Test instance at 0x10d066878> __main__.Test
Crear objeto de instancia
Al instanciar una clase, otros lenguajes de programación generalmente usan la palabra clave `new`, pero en Python no existe esta palabra clave. La instanciación de una clase es similar a una llamada de función.
A continuación se usa el nombre de la clase `Employee` para instanciar, y se reciben parámetros a través del método `__init__`.
"创建 Employee 类的第一个对象"
emp1 = Employee("Zara", 2000)
"创建 Employee 类的第二个对象"
emp2 = Employee("Manni", 5000)
Acceder a atributos
Puedes usar el punto.para acceder a los atributos del objeto. Usa el nombre de la clase de la siguiente manera para acceder a la variable de clase:
emp1.displayEmployee() emp2.displayEmployee() print "Total Employee %d" % Employee.empCount
Ejemplo completo:
Ejemplo
Al ejecutar el código anterior, el resultado es el siguiente:
Name : Zara ,Salary: 2000 Name : Manni ,Salary: 5000 Total Employee 2
Puedes agregar, eliminar y modificar atributos de la clase, como se muestra a continuación:
emp1.age = 7 # 添加一个 'age' 属性 emp1.age = 8 # 修改 'age' 属性 del emp1.age # 删除 'age' 属性
También puedes usar las siguientes funciones para acceder a los atributos:
- `getattr(obj, name[, default])`: accede al atributo del objeto.
- `hasattr(obj, name)`: verifica si existe un atributo.
- `setattr(obj, name, value)`: establece un atributo. Si el atributo no existe, crea uno nuevo.
- `delattr(obj, name)`: elimina un atributo.
Atributos de clase integrados en Python
- `__dict__`: atributos de la clase (contiene un diccionario formado por los atributos de datos de la clase)
- `__doc__`: cadena de documentación de la clase
- `__name__`: nombre de la clase
- `__module__`: módulo donde se encuentra la definición de la clase (el nombre completo de la clase es '__main__.className'; si la clase está en un módulo importado `mymod`, entonces `className.__module__` es igual a `mymod`)
- `__bases__`: todos los elementos de las clases base de la clase (incluye una tupla compuesta por todas las clases base)
A continuación se muestra un ejemplo de invocación de los atributos de clase integrados en Python:
Ejemplo
Al ejecutar el código anterior, el resultado es el siguiente:
Employee.__doc__: 所有员工的基类
Employee.__name__: Employee
Employee.__module__: __main__
Employee.__bases__: ()
Employee.__dict__: {'__module__': '__main__', 'displayCount': <function displayCount at 0x10a939c80>, 'empCount': 0, 'displayEmployee': <function displayEmployee at 0x10a93caa0>, '__doc__': '\xe6\x89\x80\xe6\x9c\x89\xe5\x91\x98\xe5\xb7\xa5\xe7\x9a\x84\xe5\x9f\xba\xe7\xb1\xbb', '__init__': <function __init__ at 0x10a939578>}
Destrucción de objetos en Python (recolección de basura)
Python utiliza la técnica simple de recuento de referencias para rastrear y recolectar la basura.
Internamente, Python registra cuántas referencias tiene cada objeto en uso.Una variable de seguimiento interna, llamada contador de referencias.
Cuando se crea un objeto, se crea un contador de referencias. Cuando el objeto ya no es necesario, es decir, cuando su contador de referencias llega a 0, el objeto es recolectado como basura. Sin embargo, la recolección no es "inmediata"; el intérprete recupera el espacio de memoria ocupado por los objetos basura en el momento adecuado.
a = 40 # 创建对象 <40> b = a # 增加引用, <40> 的计数 c = [b] # 增加引用. <40> 的计数 del a # 减少引用 <40> 的计数 b = 100 # 减少引用 <40> 的计数 c[0] = -1 # 减少引用 <40> 的计数
El mecanismo de recolección de basura no solo se dirige a objetos con contador de referencias 0, sino que también puede manejar el caso de referencias cíclicas. Una referencia cíclica se refiere a que dos objetos se referencian mutuamente, pero ninguna otra variable los referencia. En este caso, no basta con usar solo el recuento de referencias. El recolector de basura de Python es en realidad un contador de referencias y un recolector de ciclos. Como complemento al recuento de referencias, el recolector de basura también presta atención a los objetos cuya cantidad total asignada es grande (es decir, aquellos que no se destruyen mediante el recuento de referencias). En este caso, el intérprete se detiene e intenta limpiar todos los ciclos sin referencias.
Ejemplo
El destructor `__del__` se llama cuando el objeto se destruye. Cuando el objeto ya no se usa, el método `__del__` se ejecuta:
Ejemplo
El resultado de ejecutar el ejemplo anterior es el siguiente:
3083401324 3083401324 3083401324 Point 销毁
Nota:Normalmente necesitas definir una clase en un archivo separado,
Herencia de clases
Uno de los principales beneficios de la programación orientada a objetos es la reutilización de código, y una de las formas de lograr esta reutilización es mediante el mecanismo de herencia.
Las nuevas clases creadas mediante herencia se denominansubclasesoclases derivadas, y las clases heredadas se denominanclases base、clases padreosuperclases。
Sintaxis de herencia
class 派生类名(基类名)
...
Algunas características de la herencia en Python:
- 1. Si en la subclase se necesita el método constructor de la clase padre, se debe llamar explícitamente al constructor de la clase padre, o no reescribir el constructor de la clase padre. Para más detalles, consulte:Explicación sobre la subclase de Python que hereda el constructor de la clase padre。
- 2. Al llamar a un método de la clase base, es necesario añadir el prefijo del nombre de la clase base y se debe incluir el parámetro self. La diferencia es que al llamar a una función normal dentro de la clase no se necesita incluir el parámetro self.
- 3. Python siempre busca primero el método del tipo correspondiente; si no puede encontrar el método correspondiente en la clase derivada, entonces comienza a buscar en la clase base una por una. (Primero busca el método llamado en la clase actual, y solo si no lo encuentra va a la clase base).
Si se lista más de una clase en la tupla de herencia, se denomina "herencia múltiple".
Sintaxis:
La declaración de las clases derivadas es similar a la de sus clases padre; la lista de clases base heredadas sigue al nombre de la clase, como se muestra a continuación:
class SubClassName (ParentClass1[, ParentClass2, ...]):
...
Ejemplo
El resultado de ejecución del código anterior es el siguiente:
调用子类构造方法 调用子类方法 调用父类方法 父类属性 : 200
Puedes heredar de múltiples clases
class A: # 定义类 A ..... class B: # 定义类 B ..... class C(A, B): # 继承类 A 和 B .....
Puedes usar los métodos issubclass() o isinstance() para comprobarlo.
- issubclass() - función booleana que determina si una clase es subclase o clase descendiente de otra clase, sintaxis: issubclass(sub, sup)
- isinstance(obj, Class) función booleana que devuelve true si obj es un objeto instancia de la clase Class o un objeto instancia de una subclase de Class.
Sobrescritura de métodos
Si la funcionalidad del método de tu clase padre no satisface tus necesidades, puedes anular el método de tu clase padre en la subclase:
Ejemplo:
Ejemplo
El resultado de ejecutar el código anterior es el siguiente:
Llamar a métodos de la subclase
Métodos de sobrecarga básicos
La siguiente tabla enumera algunas funciones comunes que puedes anular en tus propias clases:
| Número | Método, descripción y llamada simple |
|---|---|
| 1 | __init__ ( self [,args...] ) Constructor Método de llamada simple:obj = className(args) |
| 2 | __del__( self ) Método destructor, elimina un objeto Método de llamada simple:del obj |
| 3 | __repr__( self ) Convertir a una forma legible por el intérprete Método de llamada simple:repr(obj) |
| 4 | __str__( self ) Se utiliza para convertir valores a una forma legible para las personas Método de llamada simple:str(obj) |
| 5 | __cmp__ ( self, x ) Comparación de objetos Método de llamada simple:cmp(obj, x) |
Sobrecarga de operadores
Python también admite la sobrecarga de operadores, ejemplo a continuación:
Ejemplo
El resultado de ejecución del código anterior es el siguiente:
Vector(7,8)
Atributos y métodos de clase
Atributos privados de la clase
__private_attrs: comienzan con dos guiones bajos, declaran el atributo como privado, no se puede usar ni acceder directamente fuera de la clase. Cuando se usa en métodos dentro de la claseself.__private_attrs。
Métodos de la clase
Dentro de la clase, usando ladefpalabra clave se puede definir un método para la clase. A diferencia de la definición de funciones generales, los métodos de clase deben incluir el parámetro self, y debe ser el primer parámetro.
Métodos privados de la clase
__private_method: comienzan con dos guiones bajos, declaran el método como privado, no se puede llamar fuera de la clase. Se llama dentro de la claseself.__private_methods
Ejemplo
Python cambia el nombre para incluir el nombre de la clase:
1
2
2
Traceback (most recent call last):
File "test.py", line 17, in <module>
print counter.__secretCount # 报错,实例不能访问私有变量
AttributeError: JustCounter instance has no attribute '__secretCount'
Python no permite que las clases instanciadas accedan a datos privados, pero puedes usarobject._className__attrName( nombre_del_objeto._nombre_de_la_clase__nombre_del_atributo_privado) para acceder a los atributos, consulta el siguiente ejemplo:
#!/usr/bin/python
# -*- coding: UTF-8 -*-
class Ejemplo:
__site = "www.example.com"
ejemplo = Ejemplo()
print ejemplo._Ejemplo__site
Ejecuta el código anterior, el resultado de la ejecución es el siguiente:
www.example.com
Explicación de guion bajo simple, guion bajo doble y guion bajo doble al inicio y al final:
-
__foo__: define métodos especiales, generalmente nombres definidos por el sistema, similares a__init__()etc.
-
_foo: los que comienzan con un solo guion bajo indican variables de tipo protected, es decir, el tipo protegido solo permite el acceso a sí mismo y a sus subclases, no se puede utilizar parafrom module import *
-
__foo: los de doble guion bajo indican variables de tipo privado (private), solo se permite el acceso a la propia clase.