Kelaberetiv

kəˈlabərətɪv/ 
adjective: collaborative

Bringing together the AI community in Singapore – companies, startups, researchers, students, professionals – to collaborate, find research and business opportunities and talent.

We are moving to AI Makerspace on 1 September 2019.

Have an account? Login
New user? Register
Forgot password? Reset

AI Singapore uses a 2FA login mechanism to protect your account. Learn more about it here.

Opportunities

  • Have an interesting story to share?
  • Seeking for AI talent for your organization?
  • Seeking research interns for your labs?
  • Seeking an industry partner for your AI projects?
  • Are you a researcher and seeking an industry partner to do a POC or deployment of your IP/research outcomes?

Python Data Science Toolbox (Part 1)  

  RSS

Liyi Ang
(@liyi)
Member
Joined: 11 months ago
Posts: 55
21/11/2018 9:08 pm  

Do you have any questions relating to Python Data Science Toolbox (Part 1)? Leave them here!


Quote
kevinkan
(@kevinkan)
New Member
Joined: 5 months ago
Posts: 4
19/04/2019 4:27 pm  

In Chapter 2, there is an example: 

def raise_val(n):
    """Return the inner function."""
    def inner(x):
        """Raise x to the power of n."""
        raised = x ** n
        return raised
    return inner

Question:
In the above codes, Why is "return inner" called without having to pass in the parameter to inner function?

 

 

Cheers,
Kevin Kan


ReplyQuote
ringoshin
(@ringoshin)
Active Member
Joined: 9 months ago
Posts: 9
20/04/2019 2:41 pm  

When you returned (or assigned) a function name without any argument like that in Python, you were returning (or assigning) an address to the said function. You did not call the function to perform its instructions. Best illustrated as follows using the provided example:

square_it = raise_val(2)   # define a new function to create square values
cube_it = raise_val(3)     # define a new function to create cube values
# now you can use square_it and cube_it just like any other functions
print(square_it(3))        # 3**2 = 9
print(square_it(5))        # 5**2 = 25
print(cube_it(3))          # 3**3 = 27
print(cube_it(5))          # 5**3 = 125

Using square_it as an example, by returning the address to the inner function, you are defining dynamically a new function called square_it(x) via raised_val(2). It behaves the same as if you define it directly like this:

def square_it(x):
   raised = x**2
   return raised

Why do we do it? Decorators for one. You can read the following links for more details:

https://www.datacamp.com/community/tutorials/decorators-python

https://stackoverflow.com/questions/1589058/nested-function-in-python

 


ReplyQuote
kevinkan
(@kevinkan)
New Member
Joined: 5 months ago
Posts: 4
22/04/2019 8:35 am  

Thanks for your reply, @ringoshin.

However, I dont think you might have answered my question. Ie. Why is "return inner" called without having to pass in the parameter to inner function?

The "inner" function is expecting an input "x", but the calling function "raise_val" is calling it without passing the input to it.

 

Cheers,
Kevin Kan


ReplyQuote
ringoshin
(@ringoshin)
Active Member
Joined: 9 months ago
Posts: 9
22/04/2019 2:01 pm  

Hi Kevin,

You are correct to say that when calling a function like inner(), you have to provide an argument and it should in this case return a value. However, in this example, inner() was never called. It was being referred instead.

In Python, a function is also considered an object, which means that it can be returned and assigned to a variable. You do so when writing down only the name without the parenthesis. Let's look at some examples:

def add_xy(x, y):
   return (x+y)

print(add_xy(1, 2))      # add_xy() is called and the sum of (x, y) is returned
add_xy_too = add_xy      # the function add_xy() is assigned to add_xy_too
print(add_xy_too(2, 3))  # now you can also call add_xy_too(), just like add_xy()

The function add_xy() has been applied two times, but differently. The first was to call it as a function with arguments (1, 2) and we expected it to return a value.

 The second was to assigned it as an object to the variable add_xy_too, which later we called add_xy_too() with arguments and thus expected it to return with a value.

I hope this is clearer for you now? 🙂


ReplyQuote
ringoshin
(@ringoshin)
Active Member
Joined: 9 months ago
Posts: 9
22/04/2019 2:26 pm  

Hi Kevin,

To extend the function as an object assignment concept to the raise_val() example, here's a breakdown when you call raise_val() and assign the returned value to square_it:

def raise_val(n):
    """Return the inner function."""
    def inner(x):
        """Raise x to the power of n."""
        raised = x ** n
        return raised
    return inner

square_it = raise_val(2)
print(square_t(3))
  1. raise_val() is called with an argument n=2
  2. within raise_val(), it defines a function called inner() and since n=2, it means now raised=x**2
  3. from raise_val(), it returns the function called inner() as an object. we are not calling inner(), but referring to it at this point of time, hence no need to pass any argument x.
  4. the returned value, which happens to be inner(), is now assigned to square_it
  5. since square_it has been assigned the function inner(), which in this case is defined with raised=x**2, you can treat square_it like a function and call it. When you call square_it(3), it will return 9.

ReplyQuote
Share:
  
Working

Please Login or Register