Каков наилучший способ изменить класс, вызываемый унаследованным методом после инициализации класса в Python?

#python #class #oop #inheritance

#питон #класс #ООП #наследование

Вопрос:

Я пытаюсь создать параллельную структуру классов в двух отдельных модулях, где методы классов в одном модуле, например source.py , регистрируются в модулях с одинаковыми именами receiving.py через наследование.

Моя проблема заключается в том, что если унаследованный метод in receiving.py вызывает другой класс в модуле , он будет указывать на класс в source.py , а не в receiving.py . Я понимаю, что это ожидается, но как я могу изменить, на какой класс указывает метод во время или после сопоставления, чтобы метод в receiving.py классе вызывал класс из receiving.py .

Вот схема, которая поможет проиллюстрировать проблему. схематический

Минимально достаточный пример:

source.py

 class Foo:  origin = 'src'    @classmethod  def get_origin(cls):  return cls.origin    @classmethod  def get_origin_bar(cls):  return Bar.origin   class Bar:  origin = 'src'  

receiving.py

 class Tag:  pass  class Foo(Tag):  origin = 'rec'    class Bar(Tag):  origin = 'rec'  
 def register_bases(base, module):  """  Recursive function that adds __bases__ from DataJoint Tables in base to matching classes in module.  :param base (module): source module with classes to.   :param module (module): mapping between classes and methods  """  for name in dir(base):  base_cls = getattr(base, name)  module_cls = getattr(module, name) if hasattr(module, name) else None  if module_cls and inspect.isclass(module_cls) and issubclass(module_cls, receiving.Tag):  assert base_cls not in module_cls.__bases__, f'Class "{name}" of base already in __base__ of module.'  module_cls.__bases__ = (base_cls, *module_cls.__bases__)  register_bases(base_cls, module_cls)  
 import inspect import source, receiving  # Before registering bases receiving.Foo.get_origin() -gt; AttributeError: type object 'Foo' has no attribute 'get_origin'  receiving.Foo.get_origin_bar() -gt; AttributeError: type object 'Foo' has no attribute 'get_origin_bar'  
 # register bases register_bases(source, receiving)  
 # after registering bases receiving.Foo.get_origin() -gt; 'rec'  receiving.Foo.get_origin_bar() -gt; 'src'  

Что мне нужно , так это чтобы в последней строке было указано 'rec' , что метод get_origin_bar вызывается receiving.Bar.origin вместо source.Bar.origin .

Комментарии:

1. Почему вы не можете просто связать эти классы по наследованию, тем самым избежав проблемы, которую вы создали для себя, пытаясь создать параллели? В принципе, это звучит как проблема X-Y — пожалуйста, объясните, в чем заключается реальная проблема, которую вы пытаетесь решить?

2. привет, спасибо, что нашли время. не уверен, что понимаю предложенное вами решение. Вы предполагаете, что классы в receiving.py должны наследовать от своих исходных классов путем импорта source.py в модуль? Или вы спрашиваете, почему вообще существует два модуля? Проблема, которую я пытаюсь решить, заключается в том, что один модуль существует в Docker env, а другой модуль существует в API. Я пытаюсь разделить модули так, чтобы все, что может функционировать вне среды docker, могло существовать в API, но классы docker также могут наследовать эти методы.

3. Чтобы связать его с примером. source.py будет модулем в API и receiving.py будет модулем в Docker env.

4. Боюсь, ваше объяснение не имеет никакого смысла, и диаграмма тоже не имеет смысла — как может Foo наследовать от Foo или Bar наследовать от Bar?

5. receiving.Foo наследует от source.Foo и receiving.Bar наследует от source.Bar