Search code examples
pythondynamic-function

Unable to call a function by using a string


I am trying to call a function in a class based on the string I passed in.

I tried following the steps at this link: Calling a function of a module from a string with the function's name in Python

Here is my code:

methodNameString = "add" + typeOfShip
methodToCall = getattr(listOfPlayerFleets[currentPlayer], methodNameString)

listOfPlayerFleets[currentPlayer].methodToCall(num)

I get the error:

AttributeError:fleet instance has no attribute 'methodToCall'

Any ideas as to why methodToCall isn't being assigned my correct method name?

I also tried

methodToCall = getattr(fleet, methodToCall)

then I get the message:

AttributeError: 'module' object has no attribute 'addCruiser'

Its as if the getattr can't find my methods in my class.

the listOfPlayerFleets is a list of fleet objects

Here is what the fleet object looks like you can see the methods do really exist.

class fleet:
    """ Stores Fleet Numbers, Represents a fleet """

    ships = {'fighters':0, 'cruisers':0, 'capitols':0}
    attacking = False
    defending = False

    def __init__(self):
        self.ships = {'fighters':0, 'cruisers':0, 'capitols':0}
        self.attacking = False
        self.defending = False

    #add a Fighter
    def addFighter(self, numOfFighters):
        self.ships['fighters'] = numOfFighters


    #add a Cruiser
    def addCruiser(self, numOfCruisers):
        self.ships['cruisers'] = numOfCruisers

    #add a Capitol Ship
    def addCapitol(self, numOfCapitols):
        self.ships['capitols'] = numOfCapitols

Solution

  • Your methodToCall variable is a bound method, meaning you don't need to call it on an object--it knows the object it will be called on. fleet.addFighter, for example, is an unbound method. Printing repr(methodToCall) and repr(fleet.addFighter) should make this clear.

    You should use this:

    methodNameString = "add" + typeOfShip
    methodToCall = getattr(listOfPlayerFleets[currentPlayer], methodNameString)
    
    methodToCall(num)