0

Given one of those:

def operations(x, y, z):
  def add(x,y):
    return x+y
  def sub(x,y):
    return x-y
  return z(x,y)
--------------------------------------------------
def operations(x, y, z):
  if z == add:
    def add(x,y):
      return x+y
  if z == sub:
    def sub(x,y):
      return x-y
  res = z(x,y)
  return res

I'm trying to call one of multiple inner functions from one of the outer variables function in python but I get this errors:

result = operations(10,5,add)
=>
NameError: name 'add' is not defined
--------------------------------------------------
result = operations(10,5,"add")
=>
TypeError: 'str' object is not callable

I know i could use this solution:

def add(x,y):
  return x+y
def sub(x,y):
  return x-y
def operations(x, y, z):
  return z(x,y)

But for me it seems clearer to use nested functions.

I also read this: Short description of the scoping rules? But it didn't really helped me.

  • Why do you think nested functions are clearer? You are *redefining* those functions every time you call `operations`. They are not defined once when `operations` itself is defined. – chepner Feb 04 '21 at 15:39
  • If you want to isolate them to their own namespace, use a class. – chepner Feb 04 '21 at 15:41

2 Answers2

0

Here's what I could come up with:

def operations(x, y, z: str): 
    def add(x, y): return x + y
    def sub(x, y): return x - y
    # ...
    
    if z == 'add':
        return add(x, y)

    elif z == 'sub':
        return sub(x, y)

    # elif ...
    
    else:
        print(f'Sorry, {z} is not a valid function.')
        return

Let's break down the code:

    def add(x, y): return x + y
    def sub(x, y): return x - y
    # ...

This defined all of the functions we can use. Note: I only made them one line to keep everything a bit more concise. This is not necessary.

    if z == 'add':
        return add(x, y)

    elif z == 'sub':
        return sub(x, y)

    # elif ...

These are where we parse z, and return our values. These can go on as far as you want.

    else:
        print(f'Sorry, {z} is not a valid function.')
        return

This is just a base case for when a use enters an invalid operation. For example, if you ran operations(2, 2, 'not_real_function') would return Sorry, not_real_function is not a valid function..

CATboardBETA
  • 418
  • 6
  • 29
  • Thank you for you elaborated answer but @chepner made me realize that my approach unnecessarily redefines each inner function every time outer function was called. –  Feb 04 '21 at 17:17
0

Your current approach unnecessarily redefines each of add, subtract, etc every time operations is called, not just once when operations is defined. If you want to isolate the individual operations to their own namespace, use a class.

class OperatorApplication:
    @staticmethod
    def add(x, y):
        return x + y
    
    @staticmethod
    def subtract(x, y):
        return x - y

OperatorApplication.add(x, y)
chepner
  • 497,756
  • 71
  • 530
  • 681
  • Thank you making me realize about the unnecessarily redefining and for the _class_ trick! –  Feb 04 '21 at 17:22