首页 > 解决方案 > 如何使用具有不同属性的同一类生成多个对象?

问题描述

我正在为在线系统开发一个 Python 包,并开始实现像这样工作的装饰器:

@Service
class MyCode ():
  # This will run once on beginning
  def setup (self):
    pass
  # This will run once on every loop
  def main (self):
    pass
  # This will run on an exclusive thread forever (or until program shuts down)
  def loop (self):
    pass

并想实现一个Swarm装饰器,例如

@Swarm (10)
class MyCode ():
  pass

会生成 10 个MyCode名称 like MyCode_Oto的实例MyCode_9,每个实例彼此不同。

我的Service装饰器适用于单个实例,就像这样:

from copy import deepcopy

class Service ():
  def __init__ (self, obj, context = None, name=None):
    @wraps(obj)
    def init(obj, context = None):
      try:
        if name:
          self.__name = name
        else:
          self.__name = obj.name
      except:
          self.__name = obj.__name__
      self.__context = context
      self.__rawObj = deepcopy(obj)
      self.__obj = deepcopy(obj)
      self.__obj.__init__(self.__obj)
      self.__obj.MSG_VERBOSE  = self.MSG_VERBOSE
      self.__obj.MSG_DEBUG    = self.MSG_DEBUG
      self.__obj.MSG_INFO     = self.MSG_INFO
      self.__obj.MSG_WARNING  = self.MSG_WARNING
      self.__obj.MSG_ERROR    = self.MSG_ERROR
      self.__obj.MSG_FATAL    = self.MSG_FATAL
      try:
        self.seed = self.__obj.seed
      except:
        self.seed = 0
      self._active = True
    return init(obj, context=None)

self.seed仅用于调试。

我试图这样实现Swarm

class Swarm ():
  def __init__ (self, size=1, obj=None, context=None):

    self.__context = context
    self.__services = []
    self.__name = "Otools Swarm <None>"
    self.__size = size
    if obj:
      self.__call__(obj)
    self._active = True

  def __call__ (self, obj, context=None, index=None):

    @wraps(obj)
    def init(obj, index=0):
      obj.__init__(obj)
      new_obj = deepcopy(obj)
      self.__rawObj = deepcopy(new_obj)
      self.__name = new_obj.__name__
      new_obj.name = "{}_{}".format(new_obj.__name__, index)
      svc = Service(new_obj)
      self.__services.append(svc)

    for i in range(self.size):
      init(obj, i)

    for service in self.__services:
      print ("SERVICE_DATA:", service.name, service.seed)
      print ("OBJ_DATA:", service.obj.name, service.obj.seed)

    return self

但是那些prints告诉我这个:

SERVICE_DATA: SwarmTest_0 2199
OBJ_DATA: SwarmTest_4 2643
SERVICE_DATA: SwarmTest_1 4148
OBJ_DATA: SwarmTest_4 2643
SERVICE_DATA: SwarmTest_2 1438
OBJ_DATA: SwarmTest_4 2643
SERVICE_DATA: SwarmTest_3 1341
OBJ_DATA: SwarmTest_4 2643
SERVICE_DATA: SwarmTest_4 2643
OBJ_DATA: SwarmTest_4 2643

我尝试在很多地方添加 deepcopy,尝试不调用__init__该对象,但我不知道还能做什么。

标签: pythonpython-3.xinstancedeep-copy

解决方案


感谢@chepner,我有了一个想法并修复了它。

我的解决方案:

服务.py

class Service ():
  """
  A Service is a class that shall encapsulate your own class in order to 
  attach it into a context. It has four core methods: "setup", 
  "main", "loop" and "finalize". The "setup" method will run once.
  The "main" method will run once every execution loop on the main
  thread. The "loop" method will loop forever, unless the service is
  diabled. The "finalize" method will run when the program shuts down.
  """

  def __init__ (self, obj, context = None, name=None):
    @wraps(obj)
    def init(obj, context = None):
      self.__obj = obj()
      self.__context = context
      self.__rawObj = deepcopy(obj)
      try:
        if name:
          self.__name = name
        else:
          self.__name = self.__obj.name
      except:
          self.__name = self.__obj.__class__.__name__
      self.__obj.name = self.__name
      self.__obj.MSG_VERBOSE  = self.MSG_VERBOSE
      self.__obj.MSG_DEBUG    = self.MSG_DEBUG
      self.__obj.MSG_INFO     = self.MSG_INFO
      self.__obj.MSG_WARNING  = self.MSG_WARNING
      self.__obj.MSG_ERROR    = self.MSG_ERROR
      self.__obj.MSG_FATAL    = self.MSG_FATAL
      self._active = True
    return init(obj, context=context)

群.py

class Swarm ():
  """
  A Swarm helps deploying multiple similar Service objects
  by handling everything the user should do in order to deploy
  them with much fewer lines of code.
  """

  def __init__ (self, size=1, obj=None, context=None):

    self.__context = context
    self.__services = []
    self.__name = "Otools Swarm <None>"
    self.__objName = None
    self.__size = size
    if obj:
      self.__call__(obj)
    self._active = True

  def __call__ (self, obj, context=None, index=None):

    @wraps(obj)
    def init(obj, index=0):
      self.__objName = obj.__name__
      new_obj = deepcopy(obj)
      self.__rawObj = deepcopy(new_obj)
      new_obj.name = "{}_{}".format(self.__objName, index)
      svc = Service(new_obj)
      self.__services.append(svc)

    for i in range(self.size):
      init(obj, i)

    return self

它工作正常。

完整代码:https ://github.com/gabriel-milan/otools


推荐阅读