Init супер с существующим экземпляром? - PullRequest
4 голосов
/ 09 января 2020

Предположим, у меня есть:

class Super:
  def __init__(self,a):
     self.a = a
  @classmethod
  def from_b(cls,b):
     return cls(b.to_a())

class Regular(Super):
   def __init__(self,b):
      # how to set my super to the output of
      super = super.from_b(b)

Как правильно инициализировать суперкласс с выводом метода суперкласса, а не init?

Мой OOP фон находится на C ++, и я постоянно вхожу в этот сценарий ios из-за способности перегружать конструкторы в C ++, поэтому обходной путь для этого был бы замечательным.

Ответы [ 2 ]

2 голосов
/ 10 января 2020
Ответ

@ shx2 работает, но расточительно / неловко создает одноразовый объект Super только для инициализации нового объекта Regular с его атрибутом a.

Если у вас есть контроль над источником Super, вы можете заставить метод from_b создать экземпляр данного подкласса, и вместо этого подкласс должен вызвать метод from_b в своем методе __new__, так что объект Regular может быть создан и инициализируется напрямую:

class Super:
    def __init__(self, a):
        self.a = a

    @classmethod
    def from_b(cls, b):
        obj = super().__new__(cls)
        cls.__init__(obj, b.to_a())
        return obj

class Regular(Super):
    def __new__(cls, b):
        return super().from_b(b)

, так что следующие утверждения пройдут:

from unittest.mock import Mock

obj = Regular(Mock())
assert type(obj) is Regular
assert obj.a.to_a.is_called()
2 голосов
/ 09 января 2020

Это немного неловко (поскольку то, что вы пытаетесь сделать, немного неловко), но это сработает:

class Super:
  def __init__(self,a):
     self.a = a
  @classmethod
  def from_b(cls,b):
     return cls(b.to_a())

class Regular(Super):
   def __init__(self,b):
      a = Super.from_b(b).a
      super().__init__(a)

Кстати, это может помочь помнить, что «конструктор» такой метод, как from_b() (обычно) возвращает новый объект, в то время как __init__() only инициализирует объект после его создания.

...