3

I have a file called main.py which contains the following code:

def function(a):
     def inner_function(b):
           return b**2
     print("Reached here!")

Now I have a different file named test.py and I want to import the function inner_function from main.py. Currently I am doing this in my test.py, but it's not working:

from main import function
from function import inner_function

print(inner_function(2))
Underoos
  • 4,708
  • 8
  • 42
  • 85
pikachuchameleon
  • 665
  • 3
  • 10
  • 27
  • 4
    That is not going to work. What are you actually trying to do? See [XY Problem](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). – Stephen Rauch May 14 '19 at 03:48
  • It's not possible due to lexical scoping rules. You can't even use `inner_function` from `main.py` except only from within `function` (which it is lexically scoped inside). – thebjorn May 14 '19 at 03:49
  • More than just the scope rules, it's also not going to work because `inner_function` doesn't even *exist* when you're trying to use it. – user2357112 May 14 '19 at 03:50
  • 1
    The inner function only exist while the outer function is executed and not at import time. Also, the import statement does not work as you have been using it. You can't import from objects (like functions), just from modules andpackages. – Klaus D. May 14 '19 at 03:53
  • This is usually done only for *helper* functions which doesn't need to be retained outside. Otherwise it is should be at *module* level. – Nishant May 14 '19 at 04:03
  • As mentioned in the comments here, it's not feasible, but you can make it happen by redifining your `main.py` and `test.py` @pikachuchameleon Please check my answer below :) – Devesh Kumar Singh May 14 '19 at 11:00
  • Thanks for the comments. Now I understand the issue. – pikachuchameleon May 15 '19 at 02:46

2 Answers2

4

Inner functions only exist when the code in the outer function is run, due to the outer function being called. This code, on the outer function then can use the inner function normally, and, it has the option to return a reference to the inner function, or assign it to another data structure (like append it to a list it (the outer function) is modifying).

Therefore, the example you give is no-op - the inner_funciton does nothing, even if the function is called. It is created, and then destroyed when function exits after the call to print.

One of the things that are possible to do with inner funcitons are function factories that can make use of variables - which can be simply passed as arguments to the outer function. Therefore, this works as another way in Python of creating permanent parameters for callables - the other way of doing that is by using classes and instances.

So, for this to work, your function would have to return the inner_function in its return statement - and, if, besides working, you want this to make any sense, you'd better have something else inside function that the inner_function would make use of - like a permanent parameter.

Then, on the other module, you import the outer function, and call it - the return value is the parametrized inner function:

main.py:

def multiplier_factory(n):
   def inner(m):
       return n * m
   return inner

test.py:

from main import multiplier_factory

mul_3 = multiplier_factory(3)

print(mul_3(2))  # will print 6
jsbueno
  • 99,910
  • 10
  • 151
  • 209
1

As other commentors have suggested, Inner functions are called inner for a reason, since they only exist within the scope of the function they are defined in, so your inner_function has no existence outside function, which means no existence outside main.py, as shown below

In [12]: def function(a): 
    ...:      def inner_function(b): 
    ...:            return b**2 
    ...:      print("Reached here!") 
    ...:       

#We can access function here
In [13]: function(2)                                                                                                                                                              
Reached here!

#We cannot access inner_function here
In [14]: inner_function(4)                                                                                                                                                        
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-14-11b6e7555d5a> in <module>
----> 1 inner_function(4)

NameError: name 'inner_function' is not defined

If you really want to use inner_function, we can return the inner function from the outer and use it

In [18]: def function(a): 
    ...:      def inner_function(b): 
    ...:            return b**2 
    ...:      print("Reached here!") 
    ...:      return inner_function 
    ...:                                                                                                                                                                          

#func contains inner_function
In [19]: func = function(4)                                                                                                                                                       
Reached here!

#We call inner_function via func
In [20]: func(5)                                                                                                                                                                  
Out[20]: 25

In addition you can only import classes or function from modules, and you cannot import a function from another function like your second import statement

In [21]: from function import inner_function                                                                                                                                      
---------------------------------------------------------------------------
ModuleNotFoundError                       Traceback (most recent call last)
<ipython-input-21-1b1a859581c3> in <module>
----> 1 from function import inner_function

ModuleNotFoundError: No module named 'function'

So a way to use inner_function can be

main.py

def inner_function(b):
    return b**2

test.py

from main import inner_function
print(inner_function(2))
Devesh Kumar Singh
  • 20,259
  • 5
  • 21
  • 40