【问题标题】:How can I generate multiple objects using the same class with different attributes?如何使用具有不同属性的同一类生成多个对象?
【发布时间】:2020-05-05 18:05:46
【问题描述】:

我正在为在线系统开发一个 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 实例,名称从 MyCode_OMyCode_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__,我不知道还能做什么。

【问题讨论】:

  • 看起来您希望装饰器将__init__ 方法添加到它作为参数接收的类,而不是类本身。

标签: python python-3.x instance deep-copy


【解决方案1】:

感谢@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)

Swarm.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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-05-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-26
    • 1970-01-01
    • 2015-02-18
    • 1970-01-01
    相关资源
    最近更新 更多