1

What is the scope of the function itself inside the function in python? My question arises because I finally thought about venturing into recursion ( though I am not competent enough to understand it fully). I am using Eclipse (PyDev) and inside the class, for example:

A simple recursion example for factorial widespread in every book is:

def factorial(n):
       if (n==0):
           return 1
       else:

           return n*factorial(n-1)

In another example, inside the class:

class test:

    def factorial(self,n):
       if (n==0):
           return 1
       else:
           return n*factorial(n-1)

Do I have to use self.factorial(n-1)? ( I guess, I should because PyDev is showing unidentified variable when I don't). Why is the reference to the object itself is needed in this case? Am I missing some important thing I should understand here.

5
  • 1
    This is not limited to recursion, but to any method defined within a class. Commented Oct 24, 2013 at 17:59
  • But shouldn't the function recognize itself without reference to its object when using recursion. Sorry if it is trivial but I am not understanding it properly. Commented Oct 24, 2013 at 18:00
  • No, there is no way for a function to 'recognize itself' in Python. Commented Oct 24, 2013 at 18:01
  • 1
    Python functions are first-class objects; you work with them by using references to them just like anything else. When you define a function, it is stored in the parent scope in the name you used to define it by, but you can give it any name you like after that. foo = factorial; del factorial; foo() works great too, but now there is no factorial name in the global namespace anymore. Commented Oct 24, 2013 at 18:04
  • Oh, yes! you reminded me something which I had forgotten. I am learning java and python at the same time. Too much mixing in my brain. Thanks @MartijnPieters Commented Oct 24, 2013 at 18:07

4 Answers 4

2

factorial in your first example is a global function. The fact that you call it recursively, does not change that you still first need to look up the function object to be able to call it.

In other words, the current function being called is not in any way special. factorial is still a name that needs to be dereferenced, and it doesn't matter that that name happens to reference to the function being executed.

Thus, in your second example, where factorial is instead a method, there is no global reference to that method. Instead, you find it like any other method on the class, through the self reference.

When you define a function, Python stores a reference to that new function object in the name you gave it, in the current scope. In a global scope that means that def foo() becomes a global name foo bound to a function object. You can break recursion by removing that name:

>>> def foo(): return foo()  # infinite recursion
...
>>> def foo(): return foo()  # infinite recursion
... 
>>> foo
<function foo at 0x108e4b500>
>>> bar = foo
>>> del foo
>>> foo
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'foo' is not defined
>>> bar
<function foo at 0x108e4b500>
>>> bar()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 1, in foo
NameError: global name 'foo' is not defined

Note the NameError here; I deleted foo from the global namespace, but still have a reference in bar, which I can call. But the function itself, when executed, cannot find the global name foo.

Python functions otherwise, have no reference to themselves. From inside the function, you cannot retrieve the function object itself, not reliably. The best you can do is get the original function name:

>>> def foo():
...     return sys._getframe(0).f_code.co_name
... 
>>> foo()
'foo'
>>> bar = foo
>>> bar()
'foo'

but that does not give you a guarantee that you can still access that function object through that name.

Sign up to request clarification or add additional context in comments.

Comments

1

To complement the other answers, here's a quick demonstration

def f():
   return f  # returning itself, but what does f resolve to?

# this is f
f
=> <function __main__.f>
# it is defined in the global scope
globals()['f']
=> <function __main__.f>
# when accessed from within itself, it is still itself
f()
=> <function __main__.f>

Comments

1

This has nothing to do with recursion. If you define any method, or even a class within a class, you will need to use self for functions and the class name itself for classes inside classes. Let me demonstrate:

class Foo(object):

    def happy(self):
        print "Happy"

    def size(self, var):
        self.happy()  # You need to self to call happy
        if var == 1:
            return 1
        else:
            return 1 + self.size(var - 1)  # You need to refer to self

    class Bar:

        def __init__(self):
            super(Foo.Bar, self).__init__()  # You need to refer to Foo

Referring to anything inside of a class will need to use its namespace. When you create a normal function, it becomes a part of your file's namespace.

Comments

0

Recursion is a concept above programming, but is also used inside programming.

Relating it to the real world:

Recursion is simply a reference to something itself, inside itself. For example, an acronym you may have heard of:

GNU Gnu's Not Unix

This is a recursive acronym because inside the acronym, the acronym is stated. It can lead to an interesting metaphysical/philosophical debate on the chicken or the egg, because one cannot exist without the other, and which came first?

Relating to programming:

If I may break out of formal definitions, let's call every call of a function an instance of the function.

The function is defined in the code, and then called inside itself.

The function's definition is not an instance of the code, but when it is called, it becomes its own instance. Inside the instance, other functions can be called. Function(A) can call Function(B) inside itself, for instance.

Recursion is just when Function(B) = Function(A), so that Function(A) is called again and a new instance of Function(A) is started, inside the existing instance. Because Function(A) is defined above the code, all the processor does is call the code again. It doesn't in any way rely upon the existing instance that it's in the middle of.

As such, recursion can really apply anywhere.

Humorous example of Google search, where it always wants you to auto-correct to recursion

Did this help?

Happy coding!

EDIT: Oh, and the scope of a function called inside a function is simply inside the function it was called in. Function(A) calls Function(B), that means Function(B)'s scope is inside Function(A).

4 Comments

I am not trying to understand recursion here. I understand the concept fully and I have read a lot about it to talk to some extent myself. My problem was different if you read my question above.
Oh, I'm sorry. I've misunderstood what you meant! I picked up on "not competent enough to understand it fully" and thought you were asking about a question outside of python, or programming.
What I have realized about recursion is: it is easy to read book and say this is how it works but hard to apply in daily programming practice.
Absolutely. I've barely touched upon it myself in practice, but when I do have to use it, I try to think of it in the way I mentioned above. That said, I'm not entirely sure what it is you're actually asking here, and you're probably above my level anyway, so I can't help much, I don't think. At least newbs that stumble upon this question might benefit from my answer! Haha

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.