sintaxis procedimientos print listas lista funciones ejemplos declarar como apuntes python

procedimientos - print en python



¿Es pitón para una función devolver valores encadenados/establecer variables en sí misma? (8)

Esto es lo que está mal:

>>> def f(a): ... f.x = a ... return f ... >>> r = f(1) >>> print r.x 1 >>> p = f(2) >>> print p.x 2 >>> print r.x 2

¡No se espera que r también se cambie! Así que no es una buena práctica hacerlo de esta manera.

¿Es pythonic devolver múltiples valores de una función de esta manera?

def f(): f.x = 1 f.y = 2 return f r = f() print r.x,r.y 1 2


No es pythonic, ni siquiera es razonable para cualquier lenguaje que pueda admitir tal construcción.

Lo que hace es usar el estado global de la función como portador de sus valores de salida. Para devolver un valor de una función, debe utilizar, bueno, un valor de retorno , no la función llamada. En su ejemplo, no puede estar realmente seguro de cuál es su valor de retorno:

>> def f(x): ... f.x=x ... return f ... >>> z=f(1) >>> z.x 1 >>> f(2) # <--- alters global state of the function <function f at 0x10045c5f0> >>> z.x 2 # <--- errr, five lines ago z.x was 1, no?

Se puede usar un type namedtuple o un type personalizado (aunque el uso de type() puede percibirse como un nivel demasiado bajo):

>>> def dict_as_tuple(**kwargs): ... return type(''CustomType'', (object,), kwargs)() ... >>> z = dict_as_tuple(x=1, y=2) >>> z.x 1 >>> z.y 2

Con respecto al encadenamiento del método , una forma común es devolver self (si desea cambiar el estado del objeto) o un nuevo objeto del mismo tipo (los objetos son immutable , lo que es bueno )

>>> class C(object): ... def __init__(self, x): ... self.x = x ... def add(self, y): ... return C(self.x + y) ... def mul(self, y): ... return C(self.x * y) ... >>> C(0).add(1).mul(10).x 10


No está "devolviendo valores encadenados", está creando una función que se devuelve a sí misma, después de establecer variables en sí misma.

El problema con esto es que si vuelve a invocar la función (asumiendo que no es solo una función constante como se muestra en su ejemplo) es que cada aspecto individual de la función (y entiende que r es lo mismo que f en su código) hacer que esos valores cambien. Tendrás este problema si tu programa usa o no múltiples hilos.

La forma normal de devolver múltiples valores es simplemente devolver una tupla, que puede ser la fuente de una asignación de desestructuración (secuencia). Alternativamente, si desea administrar un grupo de variables juntas, usaría un objeto. Para eso están.


No. Está cambiando un objeto global que no es seguro para subprocesos.

Más común es

return 1, 2

o, si quieres tener nombres,

return {''x'': 1, ''y'': 2}


Otra opción, si necesita conservar alguna información de estado, es usar una clase y sobrecargar el método __ llamada __ .

class f: def __call__(self): self.x = 1 self.y = 2 return self.x, self.y r = f() print(r())

Eso se imprimirá:

(1, 2)


Puedes devolver una tupla:

def f(): return 1,2 x,y = f() print x,y ... (1,2)


Todos los consejos dados hasta ahora son buenos, pero no muestran mucho código, aquí están, uno por uno.

La respuesta más común fue "devolver una tupla", que se vería así

def f(): return 1, 2 x, y = f()

Una respuesta relacionada fue ''devolver un namedtuple '':

from collections import namedtuple Point = namedtuple(''Point'', ''x y'') def f(): return Point(1, 2) r = f() print r.x, r.y

Otra idea fue usar ''objetos''.

class Foo(object): def __init__(self, x, y) self.x, self.y = x, y r = Foo(1, 2) print r.x, r.y

Usted menciona ''encadenamiento'' en su pregunta; como si quisieras llamadas repetidas a f() para dar resultados diferentes. Eso es factible, también, con generadores.

def f_gen(): for x in range(1, 10) yield x, x + 1 f = f_gen() print f() print f()


Ver otros comentarios a tu pregunta si es pythonic ...
Como una solución fácil, podrías usar una clase en su lugar ...

class cls: def __init__(self): self.x, self.y = 1, 2 r = cls() print(r.x, r.y) # 1 2