Python:对于循环填充字典项,它不应该

时间:2019-05-22 17:22:45

标签: python class dictionary for-loop boolean

这是我的生产程序的修改版本,非常简单,我在其中复制了遇到的错误。我的程序应该加载IP地址列表(用于路由器),并通过发送命令和收集返回信息来使用它们。该列表加载了所有IP,但是我的程序逻辑应跳过那些不在线的IP(online变量为False),也就是说,命令不应在那些离线的路由器中运行。

Class Router代表IP列表中的每个路由器。它具有3个对象级变量:addr代表路由器地址,online代表在线状态(TrueFalse),而infoBasic代表信息的字典,例如{'Name': 'router name', 'Uptime': 'time router is up', 'OS': 'IOS version'},依此类推。对于不在线的路由器,此字典应为空({})。主程序将永远不会与此类交互,因为它由下一个类(RouterList)实例化

class RouterList代表所有Router对象的列表,这是具有与main进行交互的方法的列表。最初,它将IP地址列表加载到routerList变量中,然后实例化每个路由器,并将IP地址作为密钥,并将Router对象作为值保存到dict routerDict中。为了混淆,我手动将第二个IP设置为离线。

RouterList中,我的getName method(以及所有其他方法)应该遍历routerDict并运行命令以获取路由器名称并将该信息写入Router对象,在dict变量infoBasic中。在这种情况下,getName调用getBasic并传递Router对象,该对象调用Router对象runComm方法并传递字符串"sh version"。在这里,不要介意愚蠢的逻辑,在我的实际生产程序中,我正在使用缓存装饰器仅运行一次命令并将其存储以备后用。

在循环内的同一getName方法中,它应跳过离线路由器。在程序结尾,我调用getRouters,它应该只打印routerList的字典及其内部信息。它不仅填充了处于脱机状态的路由器中的信息,而且还在所有路由器对象中复制了相同的信息(更具体地说,看起来它对dict的所有项目都应用了相同的内容,因此最后一个是在末尾重叠)。

这是我的完整程序:

class Router:
  addr = None
  online = False
  infoBasic = {}

  def __init__(self, addr = None):
    self.addr = addr
    if self.addr == '192.168.10.50':
      self.online = False
    else:
      self.online = True

  def runComm(self, command = None):
    if command == None:
      return "Error"
    return "Return of command for router {}".format(self.addr)

class RouterList:
  routerList = None
  routerDict = {}

  def __init__(self, routerList = None):
    if routerList == None:
      self.routerList = ['192.168.10.10', '192.168.10.50', '192.168.10.100']
    else:
      self.routerList = routerList

    for routerAddr in self.routerList:
      router = Router(routerAddr)
      self.routerDict[routerAddr] = router
    print("Router list loaded")

  def getRouters(self):
    """ Return list of routers """
    for router in self.routerDict.values():
      # print below should show the 3 routers but only .10 and .100 with infoBasic populated
      print(router.addr + ', online = ' + str(router.online) + ' - ' + str(router.infoBasic))

  def getBasic(self, *args, **kwargs):
    """ Call router runComm method and return show version output """
    return args[0].runComm("sh version")

  def getName(self):
    """ Call router runComm method and return show version output """
    for router in self.routerDict.values():
      if router.online == True:
        print('Setting name for ' + router.addr)
        # below I tried to use the self dict to write the return of getBasic
        self.routerDict[router.addr].infoBasic['Name'] = self.getBasic(router)

  def getUptime(self):
    """ Return router uptime """
    for router in self.routerDict.values():
      if router.online == True:
        # below I tried to use the router variable from the for loop to write the return of getBasic
        router.infoBasic['Uptime'] = self.getBasic(router)

if __name__ == '__main__':
  rl = RouterList()
  rl.getName()
  rl.getUptime()

  rl.getRouters()

这是输出:

# python3 simulate-error.py
Router list loaded
Setting name for 192.168.10.10
Setting name for 192.168.10.100
192.168.10.10, online = True - {'Name': 'Return of command for router 192.168.10.100', 'Uptime': 'Return of command for router 192.168.10.100'}
192.168.10.50, online = False - {'Name': 'Return of command for router 192.168.10.100', 'Uptime': 'Return of command for router 192.168.10.100'}
192.168.10.100, online = True - {'Name': 'Return of command for router 192.168.10.100', 'Uptime': 'Return of command for router 192.168.10.100'}

如您所见,在“设置名称为...”区域中,看起来确实已跳过了脱机的路由器。但是最后,所有路由器最终都获得了相同的信息。我知道我可能忽略了一些真正愚蠢而显而易见的内容,但是无论我复查多少次,我都找不到。你能帮忙吗?

0 个答案:

没有答案