JVK
JVK

Reputation: 3912

How to do python meta programming to pass code blocks around (like ruby yield)

Like ruby, how to pass code block and get it executed (yield) where you pass it. I am trying to achieve same thing in python 3.5 This is what my pseudo code looks like. How to achieve what I am trying to do. What changes would I have to make?

# Calculate all
# I want this function should yield whatever method passed to it

# THIS MUST BE A CLASS
class Calculator:

  def __init__(self):
    self.prefix = "hello"

  def calculate(self, function_name)
    local_val = 10
    print("executing {} function with {}".format(function_name, self.prefix))
    result = function_name(local_val)
    print(result)
    return result



# I want to pass these functions to Calculator().calculate() method

def add_one(x):
  return x+1

def minus_one(x):
  return x-1

def divide_in_half(x):
  return x/2



Calculator().calculate(add_one(?))
# expect this to print:
# executing add_one function with hello
# 11


Calculator().calculate(minus_one(?))
# expect this to print:
# executing minus_one function with hello
# 9

Calculator().calculate(divide_in_half(?))
# expect this to print:
# executing divide_in_half function with hello
# 5

Upvotes: 0

Views: 84

Answers (2)

Dimitris Fasarakis Hilliard
Dimitris Fasarakis Hilliard

Reputation: 160447

Initially, fix your __init__ so it doesn't complain when called with no args:

def __init__(self, prefix="hello")

use the function __name__ in the call to format done in calculate:

msg = "executing {} function with {}"
print(msg.format(function_name.__name__, self.prefix))

then pass the function objects along:

Calculator().calculate(add_one)
# expect this to print:
# executing add_one function with hello
# 11


Calculator().calculate(minus_one)
# expect this to print:
# executing minus_one function with hello
# 9

Calculator().calculate(divide_in_half)
# expect this to print:
# executing divide_in_half function with hello
# 5

Upvotes: 1

cdhowie
cdhowie

Reputation: 169028

Functions are objects in Python, so you can just do this:

Calculator().calculate(add_one)
Calculator().calculate(minus_one)
Calculator().calculate(divide_in_half)

Note that this passes the function itself and not the name of the function. (In your code, you would have to access function_name.func_name to obtain the function's name, so I would suggest renaming function_name to fn, which is short for "function.")

You don't even need to declare predefined functions. You can use the lambda syntax to pass an anonymous callable on the fly:

# Instead of add_one, for example:
Calculator().calculate(lambda x: x + 1)

Upvotes: 1

Related Questions