potapeno
potapeno

Reputation: 328

Passing a Function as a Parameter for a Class, eventually turning it into a method

Sorry if the title is confusing. I'm writing a minimalist game engine, and trying to define a class called "Area" where if the player enters the area, a function defined by the user happens. For example, one could create an instance Area(location,function) that would fire function on the player when the player enters location (for the sake of simplicity, let it be a point or something).

Note: in pseudo-python
# in init.py
...
def function(player):
    kill player
deathZone = Area(location,function)
--------------------------------------
# in player.update()
...
for area on screen:
    if player in area:
        Area.function(player)

The point of this is that the developer (aka me) can use any function they choose for the area. Is there anyway to do this, or should I try a better approach?

Upvotes: 0

Views: 52

Answers (1)

spacemanjosh
spacemanjosh

Reputation: 691

Sure, this kind of thing is certainly possible. In python, everything is an object, even a function. So you can pass around a function reference as a variable. For example try the following code:

import math

def rectangle(a, b):
    return a*b

def circle(radius):
    return math.pi * radius**2

class FunctionRunner(object):
    def __init__(self):
        self.userFunction = None
        self.userParams = None

    def setUserFunction(self, func, *params):
        self.userFunction = func
        self.userParams = params

    def runFunction(self):
        return self.userFunction(*self.userParams)


if __name__ == '__main__':
    functionRunner = FunctionRunner()
    functionRunner.setUserFunction(rectangle, 6, 7)
    print(functionRunner.runFunction())

    functionRunner.setUserFunction(circle, 42)
    print(functionRunner.runFunction())

Here you have two functions that are defined for an area, and a class called FunctionRunner which can run any function with any number of input arguments. In the main program, notice that you need only pass the reference to the function name, and any input arguments needed to the setUserFunction method. This kind of thing will allow you to execute arbitrary code on the fly.

Alternatively, you could also replace a method on your class with a reference to another function (which is what you are asking), though this seems less safe to me. But it is certainly possible. For example you could have a class like this:

class FunctionRunner2(object):
    def __init__(self):
        pass

    def setUserFunction(self, func):
        self.theFunction = func

    def theFunction(self, *params):
        pass

And then do this:

if __name__ == '__main__':

    functionRunner2 = FunctionRunner2()
    functionRunner2.setUserFunction(rectangle)
    print(functionRunner2.theFunction(6,7))

    functionRunner2.setUserFunction(circle)
    print(functionRunner2.theFunction(42))

Upvotes: 1

Related Questions