Absolutamente (para el ejemplo que proporcionó).
Las tuplas son ciudadanos de primera clase en Python
Hay una función incorporada divmod()
que hace exactamente eso.
q, r = divmod(x, y)
Hay otros ejemplos: zip
, enumerate
, dict.items
.
for i, e in enumerate([1, 3, 3]):
print "index=%d, element=%s" % (i, e)
d = dict((v, k) for k, v in adict.items())
d = dict(zip(adict.values(), adict.keys()))
Por cierto, los paréntesis no son necesarios la mayor parte del tiempo. Cita de la referencia de la biblioteca de Python :
Las tuplas se pueden construir de varias formas:
- Usando un par de paréntesis para denotar la tupla vacía: ()
- Usando una coma final para una tupla singleton: a, o (a,)
- Separar elementos con comas: a, b, c o (a, b, c)
- Usando la tupla () incorporada: tupla () o tupla (iterable)
Las funciones deben tener un solo propósito
Por lo tanto, deben devolver un solo objeto. En su caso, este objeto es una tupla. Considere la tupla como una estructura de datos compuestos ad-hoc. Hay lenguajes en los que casi todas las funciones devuelven varios valores (lista en Lisp).
A veces es suficiente regresar en (x, y)
lugar de Point(x, y)
.
Tuplas con nombre
Con la introducción de tuplas con nombre en Python 2.6, en muchos casos es preferible devolver tuplas con nombre en lugar de tuplas simples.
>>> import collections
>>> Point = collections.namedtuple('Point', 'x y')
>>> x, y = Point(0, 1)
>>> p = Point(x, y)
>>> x, y, p
(0, 1, Point(x=0, y=1))
>>> p.x, p.y, p[0], p[1]
(0, 1, 0, 1)
>>> for i in p:
... print(i)
...
0
1
Point(10.5, 11.5)
es 6 veces más lento que{'x': 10.5, 'y':11.5}
. Los tiempos absolutos son635 ns +- 26 ns
vs.105 ns +- 4 ns
. Es poco probable que cualquiera de los dos sea un cuello de botella en la aplicación; no optimice a menos que su generador de perfiles indique lo contrario. No cree clases a nivel de función a menos que sepa por qué lo necesita. Si su API requiere undict
usodict
, no tiene nada que ver con el rendimiento.En primer lugar, tenga en cuenta que Python permite lo siguiente (no es necesario el paréntesis):
q, r = divide(22, 7)
Con respecto a su pregunta, no existe una regla estricta de ninguna manera. Para ejemplos simples (y generalmente artificiales), puede parecer que siempre es posible que una función determinada tenga un solo propósito, lo que resulta en un solo valor. Sin embargo, cuando usa Python para aplicaciones del mundo real, rápidamente se encuentra con muchos casos en los que es necesario devolver múltiples valores y da como resultado un código más limpio.
Entonces, diría que hagas lo que tenga sentido y no trates de ajustarte a una convención artificial. Python admite múltiples valores de retorno, así que utilícelo cuando sea apropiado.
fuente
q, r
es una tupla.El ejemplo que da es en realidad una función incorporada de Python, llamada
divmod
. Entonces, alguien, en algún momento, pensó que era lo suficientemente pitónico como para incluirlo en la funcionalidad principal.Para mí, si hace que el código sea más limpio, es pitónico. Compare estos dos bloques de código:
seconds = 1234 minutes, seconds = divmod(seconds, 60) hours, minutes = divmod(minutes, 60) seconds = 1234 minutes = seconds / 60 seconds = seconds % 60 hours = minutes / 60 minutes = minutes % 60
fuente
Sí, devolver múltiples valores (es decir, una tupla) es definitivamente pitónico. Como han señalado otros, hay muchos ejemplos en la biblioteca estándar de Python, así como en proyectos de Python muy respetados. Dos comentarios adicionales:
El manejo de Python de los argumentos del método requiere la capacidad de devolver directamente varios valores. En C ++, por ejemplo, los argumentos del método se pueden pasar por referencia, por lo que puede asignarles valores de salida, además del valor de retorno formal. En Python, los argumentos se pasan "por referencia" (pero en el sentido de Java, no de C ++). No puede asignar nuevos valores a los argumentos del método y hacer que se refleje fuera del alcance del método. Por ejemplo:
// C++ void test(int& arg) { arg = 1; } int foo = 0; test(foo); // foo is now 1!
Comparar con:
# Python def test(arg): arg = 1 foo = 0 test(foo) # foo is still 0
fuente
Definitivamente es pitónico. El hecho de que puede devolver varios valores de una función, el modelo estándar que tendría en un lenguaje como C, donde necesita definir una estructura para cada combinación de tipos que devuelva en algún lugar.
Sin embargo, si llega al punto en el que está devolviendo algo loco como 10 valores de una sola función, debería considerar seriamente agruparlos en una clase porque en ese punto se vuelve difícil de manejar.
fuente
Devolver una tupla es genial. También tenga en cuenta el nuevo namedtuple que se agregó en python 2.6 que puede hacer que esto sea más agradable para usted: http://docs.python.org/dev/library/collections.html#collections.namedtuple
fuente
OT: Algol68 de RSRE tiene el curioso operador "/: =". p.ej.
INT quotient:=355, remainder; remainder := (quotient /:= 113);
Dando un cociente de 3 y un resto de 16.
Nota: típicamente, el valor de "(x /: = y)" se descarta ya que el cociente "x" se asigna por referencia, pero en el caso de RSRE el valor devuelto es el resto.
cf Aritmética de enteros - Algol68
fuente
Está bien devolver múltiples valores usando una tupla para funciones simples como
divmod
. Si hace que el código sea legible, es Pythonic.Si el valor de retorno comienza a ser confuso, verifique si la función está haciendo demasiado y divídalo si es así. Si se utiliza una tupla grande como un objeto, conviértala en un objeto. Además, considere usar tuplas nombre , que serán parte de la biblioteca estándar en Python 2.6.
fuente
Soy bastante nuevo en Python, pero la técnica de tuplas me parece muy pitónica. Sin embargo, tuve otra idea que puede mejorar la legibilidad. El uso de un diccionario permite acceder a los diferentes valores por nombre en lugar de por posición. Por ejemplo:
def divide(x, y): return {'quotient': x/y, 'remainder':x%y } answer = divide(22, 7) print answer['quotient'] print answer['remainder']
fuente