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
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)
That should do it.
methodNameString = "add" + typeOfShip
methodToCall = getattr(listOfPlayerFleets[currentPlayer], methodNameString)
methodToCall(num)
The getattr
gives you a reference to the method of that specific instance (listOfPlayerFleets[currentPlayer]
), so just call it with the parameters.
First off, this kind of thing is rarely on par with a proper solution, e.g. using dictionary, and even less rarely superior to those. You sould propably have a method addShip(kind, num)
that just does self.ships[kind] += num
. Much cleaner, easier to extend, DRY (don't repeat yourself) and as an extra bonus also faster.
As for the errors: listOfPlayerFleets[currentPlayer].methodToCall(num)
tries to call the method called methodToCall
(which obviously doesn't exist. getattr(listOfPlayerFleets[currentPlayer], methodNameString)
already got you the method you want, and it's a bound method, i.e. when you call methodToCall()
, the right self
is passed.
The other error ('method' object has no ...
) is because there's a difference between modules and the things (e.g. classes) contained in it. I suppose the class fleet
is in a module called fleet
? Then you need fleet.fleet
. By the way, classes should be named in CamelCase - see the style guide, PEP 8.
Did you try
func = getattr(obj, "method")
if callable(func):
result = func(args)
精彩评论