开发者

Accessing a function within a function(nested function?) [duplicate]

开发者 https://www.devze.com 2023-03-27 18:57 出处:网络
This question already has answers here: How to access a function inside a function? (6 answers) Closed 6 years ago.
This question already has answers here: How to access a function inside a function? (6 answers) Closed 6 years ago.

Python noob here. How do I get hold of the 'inner' function within the 'fib' function?

from time import sleep

class Fibonacci(object):

    def开发者_JS百科 __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()


You cannot, not unless fib returns inner somehow. inner is essentially a local variable inside the scope of fib and you can't access a function's locals from outside of it. (That wouldn't even make sense, since the locals don't exist except when the function is running. Think about it -- would it make sense to access fib's c variable from outside of the function?)


Do not use the following.

[...]
>>> 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!

You can tell simply by looking at it that it's not really Python, and for that matter it isn't really calling the "inner" function itself, it's simply creating a new function like it. I also didn't bother setting the globals 'correctly', because this is a terrible thing to do in the first place..

[I should mention that the point of the above is to note that the idea that you can't access internals from outside isn't strictly true, though it's almost never a good idea. Exceptions include interpreter-level code inspections, etc.]

Unclean! Unclean!


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

This code snippet will allow you to use inner.


The below seems to achieve what you want

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())


As stated by some of the other readers, it's a problem of scope. FWIW, this works by returning the inner function:

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()()

For reference, here's a good intro to python's scoping:

Short Description of the Scoping Rules?

0

精彩评论

暂无评论...
验证码 换一张
取 消