¿Cuáles son las opiniones de las personas sobre el uso del __call__
. Raramente lo he visto usado, pero creo que es una herramienta muy útil para usar cuando sabes que una clase se usará para algún comportamiento predeterminado.¿Cuándo se usa __call__ una buena idea?
Respuesta
Creo que su intuición es la correcta.
Históricamente, los objetos invocables (o lo que a veces he oído llamar "funtores") se han utilizado en el mundo OO para simular cierres. En C++ son frecuentemente indispensables.
Sin embargo, __call__
tiene un poco de competencia en el mundo de Python:
- Un método llamado regular, cuyo comportamiento puede ser a veces mucho más fácilmente deducir del nombre. Puede convertir a un método vinculado, que se puede llamar como una función.
- Un cierre, obtenido al devolver una función que está definida en un bloque anidado.
- Una lambda, que es una forma limitada pero rápida de realizar un cierre.
- Generadores y coroutines, cuyos cuerpos mantienen el estado acumulado como un functor.
Yo diría que el momento de usar __call__
es cuando no se beneficia de una de las opciones anteriores. Verifique los siguientes criterios, quizás:
- Su objeto tiene estado.
- Hay un claro comportamiento "primario" para su clase que es un poco tonto de nombrar. P.ej.si se encuentra escribiendo
run()
odoStuff()
ogo()
o el populardoRun()
siempre redundante, puede tener un candidato. - Su objeto tiene un estado que excede el que se esperaría de una función del generador.
- Su objeto envuelve, emula o abstrae el concepto de una función.
- Su objeto tiene otros métodos auxiliares que pertenecen conceptualmente a su comportamiento principal.
Un ejemplo que me gusta son los objetos de comando UI. Diseñado para que su tarea principal sea ejecutar el comando, pero con métodos adicionales para controlar su visualización como un elemento del menú, por ejemplo, me parece que es el tipo de cosas para las que aún desea un objeto llamable.
Úselo si necesita que sus objetos a ser exigible, eso es lo que está ahí para
No estoy seguro de lo que entendemos por comportamiento predeterminado
Un lugar que he encontrado que es particularmente útil es cuando se usa un contenedor o somesuch donde el objeto se llama profundamente dentro de algún framework/biblioteca.
Urgh. La pregunta parece realmente tonta ahora. Por comportamiento predeterminado quise decir que aunque las clases a menudo tienen varios métodos, a menudo hay un flujo de trabajo muy regular desde los datos hasta la salida de datos. Me preguntaba si '__call__' se puede usar para aumentar la velocidad de acceso a ese flujo de trabajo estándar. –
Bueno, un poco. No sé exactamente qué quiere decir con "aumentar la velocidad de acceso a ese flujo de trabajo estándar". '__call__' en general no tiene nada que ver con la velocidad. Puede guardar una búsqueda de atributos si usa 'obj()' en lugar de algo como 'obj.function_name()' pero eso no vale la pena mencionarlo. – nils
@Tim McNamara: Correcto. La pregunta es tonta. Particularmente la parte de "opinión" de eso. –
En términos más generales, Python tiene un lote de métodos de doble subrayado. Están ahí por una razón: son la forma de Python de sobrecargar a los operadores. Por ejemplo, si desea una nueva clase en la que además, no sé, imprime "foo"
, defina los métodos __add__
y __radd__
. No hay nada intrínsecamente bueno o malo en esto, así como tampoco hay nada bueno o malo en usar los bucles for
.
De hecho, usar __call__
es a menudo el enfoque más Pythonic, porque fomenta la claridad del código. Puede reemplazar MyCalculator.calculateValues(foo)
con MyCalculator(foo)
, por ejemplo.
¿Es MyCalculator (foo) o theCalculatorObject (foo)? – Nabin
Se usa generalmente cuando la clase se utiliza como función con contexto de instancia, como DecoratorClass que se usaría como @DecoratorClass('some param')
, por lo que 'algún parámetro' se almacenaría en el espacio de nombres de la instancia y se llamaría instancia como decorador real.
No es muy útil cuando su clase proporciona algunos métodos diferentes, ya que generalmente no es obvio cuál sería la llamada, y explícito es mejor que implícito en estos casos.
- 1. Cuándo debería implementar __call__
- 2. ¿Cuándo no es una buena idea pasar por referencia?
- 3. ¿Cuándo es una buena idea la herencia virtual?
- 4. ¿Campos multivalorados una buena idea?
- 5. Evaluar: ¿cuándo se usa?
- 6. ¿Cuándo se usa StringIO?
- 7. ¿Cuándo se usa una forma de inicio?
- 8. Objetos que se envían a sí mismos, ¿una buena idea?
- 9. ¿Cuándo se usa realmente ChannelUrl?
- 10. Instanciación explícita: ¿cuándo se usa?
- 11. ¿Cuándo es una buena idea devolver un puntero a una estructura?
- 12. Cookies de sesión firmadas. ¿Una buena idea?
- 13. ¿Cuándo tener una columna de identidad no es una buena idea?
- 14. cambiar a mysqli una buena idea?
- 15. sqlite e hibernate - es una buena idea?
- 16. Bloquear para manejar concurrencia-- una buena idea?
- 17. ¿Es una buena idea una clase de "preferencias maestras"?
- 18. activerecord como modelo, ¿es esta una buena idea?
- 19. Implementar una clase "LazyProperty": ¿es esta una buena idea?
- 20. ¿Cuándo se usa realmente el paquete savedInstanceState?
- 21. ¿Cuándo se usa cada algoritmo de clasificación?
- 22. C++ 11 protector de salida de alcance, ¿una buena idea?
- 23. ¿Qué es una Propiedad de Dependencia y cuándo se usa?
- 24. ¿Cuándo se usa una instancia de la decisión correcta?
- 25. ¿Es una buena idea devolver "const char *" de una función?
- 26. ¿Es una buena idea usar una función CreateUUID() como sal?
- 27. ¿Cuándo es mono una buena opción sobre .net?
- 28. ¿Es correcto (VERDADERO) una buena idea en C?
- 29. ¿Es una buena idea comparar double.MaxValue para la igualdad?
- 30. Análisis de hilos estáticos: ¿Buena idea?
-1: No es una pregunta de "opinión". No es "práctico" para las cosas. Simplemente ** se requiere ** para hacer un ** objeto invocable **. –
La pregunta está más centrada en cuándo es beneficioso tener objetos invocables. El método '__call__' es simplemente el vehículo para lograr eso. Estoy más interesado en el comportamiento que en el mecanismo para lograr el comportamiento. Si desea votar la pregunta, debe hacerlo con el botón de flecha, en lugar de su comentario. –
Por lo general, se considera educado indicar mediante un comentario por qué una publicación fue rechazada y si la publicación se puede mejorar. Suponiendo que el comentario se hace _politely_, por supuesto. –