2011-08-14 26 views
8

Nodo de Python aquí. ¿Cómo puedo obtener la función 'interna' dentro de la función 'fib'?Acceder a una función dentro de una función (función anidada?)

from time import sleep 

class Fibonacci(object): 

    def __init__(self, a, b, limit=50): 
     self.a = a 
     self.b = b 
     self.limit = limit 

    def fib(self): 

     while self.a < self.limit: 
      c = self.a + self.b 
      sleep(1) 
      print self.a, 
      self.b = self.a 
      self.a = c 

     def inner(self): 
      print 'Damn it! Just print already!' 


j = Fibonacci(0,1,2) 
j.fib() 

## This doesn't work. Gives an "AttibuteError: 'function' object has no attribute 'inner'" 
j.fib.inner() 
+1

Mi Python es oxidado, pero estoy bastante seguro de que no se puede acceder desde fuera inner' '' de fib', sin necesidad de cambiar la forma en 'inner' se define. –

+1

seykom, Necesita aceptar respuestas a más de sus preguntas. Haga clic en la marca de verificación junto a la respuesta que más le ayudó. Debería hacer esto tanto para sus viejas preguntas como para las nuevas. – agf

+0

¿Por qué necesita hacer esto? ¿Has considerado simplemente no anidar las funciones? Especialmente dado que la interfaz para 'inner' parece que quieres que sea un método de un objeto' Fibonacci' ... no funcionará así como una función interna ... –

Respuesta

11

No se puede, no a menos fib vuelve inner de alguna manera. inner es esencialmente una variable local dentro del alcance de fib y no se puede acceder a los locales de una función desde fuera de ella. (Eso ni siquiera tendría sentido, ya que los locales no existen, excepto cuando la función se está ejecutando. Piénselo: ¿tendría sentido acceder a la variable fibc desde fuera de la función?)

+0

Ya veo. ¡¡¡Gracias!!! – kassold

1

Como lo expresaron algunos de los otros lectores, es un problema de alcance. Fwiw, esto funciona mediante la devolución de la función interna:

from time import sleep 

class Fibonacci(object): 

    def __init__(self, a, b, limit=50): 
     self.a = a 
     self.b = b 
     self.limit = limit 

    def fib(self): 

     while self.a < self.limit: 
      c = self.a + self.b 
      sleep(1) 
      print self.a, 
      self.b = self.a 
      self.a = c 

     def inner(): 
      print 'Damn it! Just print already!' 

     return inner 


j = Fibonacci(0,1,2) 
j.fib()() 

Para referencia, aquí es una buena introducción a la determinación del alcance de pitón:

Short Description of the Scoping Rules?

+0

Gracias. ¿Por qué no hay necesidad de 'self' en' inner' – kassold

+0

Porque 'inner' no es un método de una instancia de clase. – kindall

+0

Dado que ya no se invoca a inner en el objeto (j), inner se devuelve como una función independiente. En otras palabras, inner no es un método de la clase Fibonacci, es solo una función independiente. –

7

No use el siguiente.

[...] 
>>> j = Fibonacci(0,1,2) 
>>> j.fib() 
0 1 1 
>>> # dark magic begins! 
>>> import new 
>>> new.function(j.fib.im_func.func_code.co_consts[2],{})(None) 
Damn it! Just print already! 

Se puede decir simplemente con mirarlo de que en realidad no es Python, y para el caso en realidad no es llamar a la función "interior" en sí, es simplemente crear una nueva función como él. Además, no me molesto en el establecimiento 'correctamente' las variables globales, ya que esto es una cosa terrible a hacer en primer lugar ..

[Debo mencionar que el punto de lo anterior es tener en cuenta que la idea de que pueda El acceso a los internos desde el exterior no es estrictamente cierto, aunque casi nunca es una buena idea. Las excepciones incluyen inspecciones de códigos de nivel de intérprete, etc.]

Unclean! ¡Inmundo!

+0

Por supuesto, en el caso general necesitarás usar el desensamblador y/o una considerable cantidad de capacidad intelectual y/o prueba y error para encontrar el índice correcto en 'co_conts'. .. –

+0

Deberías usar 'types.FunctionType' :) – schlamar

+0

¡Gracias! Si bien es algo terrible de hacer cuando controla el código usted mismo, puede ser útil para depurar la función de otra persona. –

5
from time import sleep 

class Fibonacci(object): 

    def __init__(self, a, b, limit=50): 
     self.a = a 
     self.b = b 
     self.limit = limit 

    def fib(self): 

     while self.a < self.limit: 
      c = self.a + self.b 
      sleep(1) 
      print self.a, 
      self.b = self.a 
      self.a = c 

     def inner(self): 
      print 'Damn it! Just print already!' 
     Fibonacci.fib.inner = inner 

    fib.inner = None 

Este fragmento de código le permitirá utilizar inner.

4

La continuación parece lograr lo que quiere

from types import CodeType, FunctionType 

def find_nested_func(parent, child_name): 
    """ Return the function named <child_name> that is defined inside 
     a <parent> function 
     Returns None if nonexistent 
    """ 
    consts = parent.func_code.co_consts 
    for item in consts: 
     if isinstance(item, CodeType) and item.co_name==child_name: 
      return FunctionType(item, globals()) 
Cuestiones relacionadas