Можно ли вызывать __init__ из __setstate__
Я улучшаю существующий класс, который делает некоторые вычисления в __init__
функция для определения состояния экземпляра. Это нормально звонить __init__()
от __getstate__()
чтобы повторно использовать эти расчеты?
3 ответа
Подводя итог реакции от Kroltan и Jonsrharpe:
Технически это нормально
Технически это будет работать, и если вы сделаете это правильно, это можно считать ОК.
Практически это сложно, избегайте этого
Если вы измените код в будущем и коснитесь __init__
тогда легко (даже вам) забыть об использовании в __setstate__
и тогда вы попадаете в сложную для отладки ситуацию (спрашиваете себя, откуда она).
class Calculator():
def __init__(self):
# some calculation stuff here
def __setstate__(self, state)
self.__init__()
Все расчеты лучше изолировать в другом общем методе:
class Calculator():
def __init__(self):
self._shared_calculation()
def __setstate__(self, state)
self._shared_calculation()
def _shared_calculation(self):
#some calculation stuff here
Таким образом, вы заметите.
Примечание: использование "_" в качестве префикса для общего метода является произвольным, вам не нужно это делать.
Обычно предпочтительнее написать метод __getnewargs__
вместо. Таким образом, механизм травления будет вызывать __init__
для вас автоматически.
Другой подход заключается в настройке класса конструктора __init__
в подклассе. В идеале лучше иметь один класс конструктора и менять его в соответствии с вашими потребностями в подклассе.
class Person:
def __init__(self, name, job=None, pay=0):
self.name = name
self.job = job
self.pay = pay
class Manager(Person):
def __init__(self, name, pay):
Person.__init__(self, name, 'title', pay) # Run constructor with 'title'
Вызов класса конструкторов таким способом оказывается очень распространенным шаблоном кодирования в Python. Сам Python использует наследование для поиска и вызова только одного __init__
метод во время построения - самый низкий в дереве классов.
Если вам нужно выше __init__
методы, которые должны быть запущены во время создания, вы должны вызывать их вручную, и обычно через имя суперкласса, как показано в коде выше. таким образом вы расширяете конструктор суперкласса и полностью заменяете логику в подклассе
Как предположил Ян, это сложно, и вы попадете в сложную ситуацию отладки, если вы вызовете его в том же классе