2011-02-25 10 views
8

En lugar de usar un OOP común, como Java y C# do con su clase base Object o object, Python usa métodos especiales para el comportamiento básico de los objetos. Python usa __str__ que se utiliza cuando el objeto se pasa a print:Motivo de OOP poco común en Python?

>>> class Demo: 
>>> def __str__(self): 
>>>  return "representation" 

>>> d = Demo() 
>>> print(d) 
representation 

Lo mismo con len:

>>> class Ruler: 
>>> def __len__(self): 
>>>  return 42 

>>> r = Ruler() 
>>> len(r) 
42 

lo que esperaría es algo como esto:

>>> class Ruler: 
>>> def len(self): 
>>>  return 42 

>>> r = Ruler() 
>>> r.len() 
42 

Lo ¿Es la razón para usar métodos especiales de forma indirecta en lugar de llamar directamente a los métodos habituales?

+2

En cuanto a \ _ \ _ str \ _ \ _, como yo lo entiendo, es estrictamente equivalente a toString de Java/C#. \ _ \ _ str \ _ \ _ da una representación textual del objeto, que es claramente diferente de lo que lo hace la impresión: imprime la representación textual en el resultado estándar. – ChrisJ

+4

¿Es esto lo que quieres decir? http://docs.python.org/faq/design.html#why-does-python-use-methods-for-some-functionality-eg-list-index-but-functions-for-other-eg-len- list –

+0

@Thomas sí, esa es la respuesta. Tal vez quieras escribirlo como una respuesta ... – deamon

Respuesta

13

La razón de esto se explica bien en la documentación de Python aquí:

http://docs.python.org/faq/design.html#why-does-python-use-methods-for-some-functionality-e-g-list-index-but-functions-for-other-e-g-len-list

La razón principal es la historia. Las funciones se usaron para aquellas operaciones que fueron genéricas para un grupo de tipos y que estaban destinadas a funcionar incluso para objetos que no tenían métodos en todos (por ejemplo, tuplas). También es conveniente tener una función que puede aplicarse fácilmente a una colección de objetos amorfa cuando utiliza las características funcionales de Python (map(), apply() et al).

De hecho, la aplicación de len(), max(), min() como una función incorporada es código en realidad menos de la aplicación de como métodos para cada tipo. Uno puede objetar casos individuales pero es parte de Python, y es demasiado tarde para hacer tales cambios fundamentales ahora. Las funciones deben permanecer en para evitar la rotura masiva de códigos.

(Esto fue respondida en los comentarios, pero necesita ser mostrado como una respuesta real por el bien de los futuros lectores.)

+2

Me lo ganaste ;-) –

+1

Otro [buen argumento] (http://lucumr.pocoo.org/2011/7/9/python-and-pola/) es que las funciones como 'len' están dando lugar a una API más consistente. – deamon

4

Estos no son ganchos.

Son solo métodos con nombres especiales.

La convención para nombres de métodos especiales en Python es __name__.

Las funciones incorporadas de len, iter, str, repr (y otras) usan métodos comunes con nombres que siguen una convención especial para que todos podamos estar seguros de haber implementado los métodos especiales correctamente.

Los métodos especiales tienen nombres que parecen extraños para que podamos usar cualquier nombre que queramos sin temor a una colisión.


obj.len() sería mucho más intuitivo de implementar y utilizar.

Para ti, quizás. Para otros, puede ser completamente desconcertante.

Python tiene ambos notación de métodos y notación de funciones para muchas funciones comunes.

Y se prefiere la notación de función.

Todavía es la programación de OO. Solo la notación ha sido cambiada.

+0

Ok, llamémoslo "métodos especiales". ¿Por qué '__len__' solo se llama indirectamente? obj.len() sería mucho más intuitivo de implementar y usar. – deamon

+0

Esto no llega al corazón de su pregunta. – FogleBird

+0

@FogleBird: me alegra que hayas entendido el corazón de la pregunta. Claramente, no pude entenderlo. –

0

Los ganchos permiten redefinir el comportamiento de funciones estándar. Considere la anulación de __add__() y utilice el operador estándar infijo + frente a la adición de un add() personalizado y el uso de llamadas anidadas.

Por otra parte, si se define __iter__(), puede utilizar su objeto en un bucle for ... in. Compáralo con controlar un ciclo y avanzar la iteración a mano. Considere anular __call__() y convertir sus instancias en funciones, tan bueno como cualquier otra función. Esto le da una enorme flexibilidad.

Si lo desea, Java hace lo mismo con .toString() que funciona implícitamente al imprimir el objeto o concatenarlo a una cadena.

0

No es un Pythonista, así que esto puede estar muy lejos, pero si entiendo su pregunta, mi impresión es que es una cuestión de estilo y modismo en lugar de comportamiento.Java, y en menor medida C#, son lenguajes muy detallados, canónicos y ortogonales. Todo es un objeto (o para C#, se comporta como - IIRC int.toString() es válido), y todo lo que hace su programa debe expresarse explícitamente.

Python es más escueto, valorando la conveniencia a expensas ocasionales de la claridad. Verá esto también en C++, con conversiones implícitas y sobrecarga operativa. Basta con contemplar el análogo C++ para sus toString() ejemplos:

std::ostream& operator<<(std::ostream& outstream, const Widget& rhs) 
{ 
    return outstream << rhs.name(); 
} 

std::cout << myWidget; 
+0

Creo que tienes razón al respecto: Python busca un equilibrio entre explícito y compacto. Pero también en Python, todo hereda de 'object', y puedes hacer' someint .__ str __() 'si quieres (no se recomienda, pero hace lo mismo que' str (someint) '). –

Cuestiones relacionadas