¿Es posible pasar una función escrita desde cero a otra función o instanciación de clase?

Esto es lo que tengo en este momento:

class Foo(Object):
    def __init__(self, name, somefunction):
        self.name = name
        self.somefunction = somefunction

def afunction(param1, param2):
    return param1 + param2

Bar = Foo("Something", afunction)

Bar.somefunction(2, 3)
#returns 5

Me pregunto si es posible no tener que declarar afunction de antemano, sino simplemente escribir el código directamente como un parámetro a somefunction durante la creación de instancias. ¿Algo como esto?

class Foo(Object):
    def __init__(self, name, somefunction):
        self.name = name
        self.somefunction = somefunction

Bar = Foo("Something", def afunction(param1, param2): return param1 + param2)

#OR

Bar = Foo("Something", Anonymousfunctiontechnique: return param1 + param2)

Bar.somefunction(2, 3)
#returns 5

Y además, ¡este no es un trabajo para lambda! Las funciones pueden ser bastante complejas, las cuales llaman dentro de ellas y con múltiples parámetros. Además, no debería poder acceder a él en ningún otro lugar (por lo que parece que una declaración externa no funcionará).

¿Es posible algo así? ¿Si es así, cómo? Y si no, ¿cuál sería la mejor manera de hacer lo que estoy tratando de hacer?

¡¡¡Gracias!!!

1
Pictraz 31 ago. 2014 a las 17:57

2 respuestas

La mejor respuesta

No puede hacer esto en Python más allá de las limitaciones de lambda.

Pero puede definir la función justo encima de la llamada y pasarla, incluso si está en otro ámbito, haciendo que su nombre sea una variable temporal que no contamine su espacio de direcciones.

La diferencia lógica entre

Bar = Foo("Something", def afunction(param1, param2): return param1 + param2)

Y

def _foo(param1, param2): return param1 + param2
Bar = Foo("Something", _foo)

Es la misma diferencia que entre

Bar = foo(param1 + param2)

Y

_good_name = param1 + param2
Bar = foo(_good_name)

Tener nombres para cualquier cálculo compuesto es una buena idea para fines de documentación. También ayuda a las personas a usar cualquier buen depurador. Y mantiene las consideraciones de formato al mínimo. En total: solo nombra cosas .

La razón por la que esto queda "excluido" de Python se reduce a:

  1. ¿Cuántas personas no asignarían un cálculo en línea a lo largo de tres líneas a una variable local?
  2. ¿Cuántas de estas funciones tienen menos de tres líneas de largo?
  3. ¿Entonces, para qué molestarse?

(Siempre uso un guión bajo para hacer esto. Los guiones bajos marcan estos 'privados', pero no son miembros, en general, por lo que solo enfatiza que son efímeros. Si el alcance los obliga a ser miembros, indica a las personas que son internos y no para un consumo más amplio. Si está totalmente paranoico sobre el desorden de clases, use los mismos una y otra vez y del al final de la definición de clase).

3
Jon Jay Obermark 31 ago. 2014 a las 14:16

Lo que estás preguntando es realmente sobre una forma de definir funciones en línea.

Desafortunadamente, Python no es compatible con esto. La gente ha preguntado sobre esto antes.

En este PEP:

lambda no será renombrado.

En un momento, lambda estaba programado para su eliminación en Python 3000. Desafortunadamente, nadie pudo encontrar una mejor manera de proporcionar funciones anónimas. Y entonces lambda está aquí para quedarse.

Pero está aquí para quedarse como está. Agregar soporte para declaraciones no es un comienzo. Requeriría permitir expresiones lambda de líneas múltiples, lo que significaría que podría existir una expresión de líneas múltiples de repente. Eso permitiría argumentos de varias líneas para las llamadas a funciones, por ejemplo. Eso es simplemente feo.

Tema: "sintaxis genexp / lambda", http: / /mail.python.org/pipermail/python-3000/2006-April/001042.html

0
simonzack 31 ago. 2014 a las 13:59