无法通过字符串调用函数
我想根据我传入的字符串来调用一个类里的函数。
我试着按照这个链接里的步骤操作:从字符串中调用模块的函数
这是我的代码:
methodNameString = "add" + typeOfShip
methodToCall = getattr(listOfPlayerFleets[currentPlayer], methodNameString)
listOfPlayerFleets[currentPlayer].methodToCall(num)
我遇到了这个错误:
AttributeError:fleet instance has no attribute 'methodToCall'
有没有人知道为什么methodToCall没有被正确赋值为我的方法名?
我还试过:
methodToCall = getattr(fleet, methodToCall)
然后我收到了这个消息:
AttributeError: 'module' object has no attribute 'addCruiser'
感觉就像是getattr找不到我类里的方法一样。
listOfPlayerFleets是一个舰队对象的列表。
这是舰队对象的样子,你可以看到这些方法确实是存在的。
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
4 个回答
首先,这种做法通常不如用字典来解决问题,甚至更少会比那些方法更好。你应该有一个方法叫 addShip(kind, num)
,它的功能就是 self.ships[kind] += num
。这样做更简洁,扩展起来也更方便,遵循了“不要重复自己”的原则,而且额外的好处是速度也更快。
关于错误:listOfPlayerFleets[currentPlayer].methodToCall(num)
试图调用一个叫 methodToCall
的方法,但显然这个方法并不存在。其实 getattr(listOfPlayerFleets[currentPlayer], methodNameString)
已经帮你找到了你想要的方法,而且它是一个 绑定方法,也就是说,当你调用 methodToCall()
时,正确的 self
会被传递进去。
另一个错误('method' object has no ...
)是因为模块和模块里面的东西(比如类)之间是有区别的。我猜 class fleet
是在一个叫 fleet
的模块里?那么你需要用 fleet.fleet
。顺便提一下,类的命名应该使用驼峰命名法,具体可以参考风格指南 PEP 8。
这样就可以了。
methodNameString = "add" + typeOfShip
methodToCall = getattr(listOfPlayerFleets[currentPlayer], methodNameString)
methodToCall(num)
getattr
这个东西可以让你拿到某个特定实例(比如listOfPlayerFleets[currentPlayer]
)的方法的引用,所以你只需要用参数去调用它就行了。
你的 methodToCall
变量是一个绑定的方法,这意味着你不需要在一个对象上去调用它——它已经知道自己会在哪个对象上被调用。比如说,fleet.addFighter
是一个未绑定的方法。打印 repr(methodToCall)
和 repr(fleet.addFighter)
会让这个区别变得更清楚。
你应该使用这个:
methodNameString = "add" + typeOfShip
methodToCall = getattr(listOfPlayerFleets[currentPlayer], methodNameString)
methodToCall(num)