-2

I want to be able to do something like this:

def calculations(a,b):
    def add(a,b):
        return a+b
    def subtract(a,b):
        return a-b

def other_function(calculations,c,d):
    return calculations(c,d) + 10

result = other_function(add,10,5)
print(result)
>>> 25

This is just a simplified example but I want to be able to let the function "calculations" do 2 different things without passing this choice as a function parameter.

Then, I would like to use this choice as a function parameter to another function "other_function".

Something similar seems to work when defining "calculations" as a class but this is not what I want to use.

Even though it seems not very practical to define "add" and "subtract" inside another function, this is what I want to do.

Clapham
  • 351
  • 2
  • 9
  • 1
    "I want to be able to let the function "calculations" do 2 different things without passing this choice as a function parameter" - how will `calculations` know what to do if you don't pass the choice to it? – rdas Oct 11 '19 at 11:28
  • Maybe something like calculations().add(a,b) ? Which is not directly a function parameter but just a specification. – Clapham Oct 11 '19 at 11:29
  • Possible duplicate of [Python function as a function argument?](https://stackoverflow.com/questions/6289646/python-function-as-a-function-argument) – mulaixi Oct 11 '19 at 11:29
  • @mulaixi I know that a function can be passed as a function argument. This is not my main question. – Clapham Oct 11 '19 at 11:30
  • 2
    @Clapham at that point `calculations` might as well be a class. In fact, the code you pasted will work if it was. – rdas Oct 11 '19 at 11:30
  • Your code works fine if you remove functions add and subtract out of function calculations. – sanyassh Oct 11 '19 at 11:31
  • @rdas I know, but does this work when avoiding classes and instead using a function? This is a requirement of my assignment. – Clapham Oct 11 '19 at 11:33

5 Answers5

1

You can pass the function and it doesn't have to (and shouldn't be) inside another function.

This will work just fine if you get rid of the outer function!

def add(a,b):
    return a+b

def subtract(a,b): # you also had a typo here - it's subtrack, not sub_S_track ;)
    return a-b

def other_function(calculations,c,d):
    return calculations(c,d) + 10

result = other_function(add,10,5)
print(result)

What happened?

calculations in other_function is just a parameter name (you pass it when calling the function!).

h4z3
  • 5,265
  • 1
  • 15
  • 29
  • Thank you for your answer. The typo is fixed ;) Even though this might not seem very practical, would it theoretically be possible to include "add" and "subtract" in another function and have it working? – Clapham Oct 11 '19 at 11:39
  • 1
    @Clapham No. `def` defines a scope. Functions inside functions are local, they are like other variables inside that function. Also, Python prefers flatness - as opposed to compiled languages, names are looked up every time something happens. I'll find you a text that comments on that – h4z3 Oct 11 '19 at 11:43
  • @Clapham http://dirtsimple.org/2004/12/python-is-not-java.html This is where I found the info about practices from compiled languages that don't work in Python. The thing about flatness is actually from The Zen of Python (do `import this` in the python interpreter): `Simple is better than complex. Complex is better than complicated. Flat is better than nested. ` – h4z3 Oct 11 '19 at 11:47
  • Thank you, maybe it doesn't work then what I was trying to do. If I get something then I'll post it here. – Clapham Oct 11 '19 at 12:00
0

you can define one function like this:

def calculate(mode, a, b):
    if mode == "add":
        return a + b
    elif mode == "substract":
        return a - b

and you can add whatever operations you want to this function

  • The point is that I don't want to add the "mode" as function parameter. – Clapham Oct 11 '19 at 11:34
  • @Clapham If you don't pass it, how can the function know what to do? Computers are not mind-readers, algorithms need clear instructions what to do. – h4z3 Oct 11 '19 at 11:38
  • There is no way you could specify an operation with just two numbers as the numbers operated on, you definietly need more information for that – Mulham Jarjanazi Oct 11 '19 at 11:46
0

You could hand in a string and put the functions in a dictionary:

def calculations(key, a,b):
    def add(a, b):
        return a + b
    def substract(a, b)
        return a - b
    fns = {"add": add, "substract": substract}
    return fns[key](a, b)


result = calculations("add", 10, 5)

This is pretty wasteful though because you redefine the inner functions every time calculations is executed.

L3viathan
  • 26,748
  • 2
  • 58
  • 81
  • Does this only work when including "key" as function parameter? Couldn't something like - calculations().add(a,b) - work somehow? I know this syntax doesn't work but maybe something similar? – Clapham Oct 11 '19 at 11:36
  • 1
    @Clapham You can't use class syntax for functions. Functions inside other functions are local. – h4z3 Oct 11 '19 at 11:39
  • @h4z3 Is it possible to define these functions to be global? – Clapham Oct 11 '19 at 11:44
0

Here's a solution using namedtuple to get what you want.

from collections import namedtuple
ops = namedtuple('Ops', ['add', 'subtract'])


def add(a, b):
    return a + b


def subtract(a, b):
    return a - b


def calculations():
    return ops(add, subtract)


def other_function(calc, a, b):
    return calc(a, b) + 10


result = other_function(calculations().add, 10, 5)

Using a class would be much cleaner.

rdas
  • 20,604
  • 6
  • 33
  • 46
0

Resulting from all the discussion here, I've figured out what I want. Thank you for your input!

def calculations(a,b):

    global add
    def add(a, b):
        return a + b

    global subtract
    def subtract(a, b):
        return a - b

    return add, subtract

def other_function(calculations, a, b):
    e = a + 19
    return calculations(e, b)

a = 10
b = 5

calculations(a,b)
result = other_function(add, a,b)
print(result)
>>>

It's by no means pythonic or elegant but satisfied the following conditions which I was looking for:

  • two functions - "add", "substract" - inside another function "calculations"
  • call one of those functions - "add" - without specifying it as function parameter of "calculations"
  • use this chosen function as a parameter for another function "other_function"
Clapham
  • 351
  • 2
  • 9
  • 1
    If you make them global, there's no point in making the `def calculations`. It's just a piece of code that does nothing. It definitely doesn't help with readability, so it's also un-pythonic. – h4z3 Oct 11 '19 at 12:21
  • Ok, maybe the assignment doesn't make sense then because I had to follow the requirements stated above. Even though this is useless in terms of fuctionality then, thank you for pointing it out and thank you for your time! – Clapham Oct 11 '19 at 12:25