2014-02-18 15 views
1

Я просматривал некоторые из кода из serge pygame engine и я кулачок через что-то в serge.serialize, что я не мог обернуть мою голову вокруг:Почему python `__setstate__` принимает` None` как параметр?

def __setstate__(self, state=None): 
     """Initialize the object to the given state for unpickling""" 
     self.initial_properties = Bag() 
     # 
     # Initialize first from the defaults and then from the live state 
     for this_state in (self.__class__._getProperties(), state): 
      if this_state: 
       for name, value in this_state: 
        setattr(self, name, value) 
        setattr(self.initial_properties, name, value) 

Этот метод был получен из Serializable объекта. Что меня смущает, почему параметр state в __setstate__ имеет значение по умолчанию None. Почему бы не отправить состояние на __setstate__ при расклеивании объекта и в какой ситуации это было бы полезно?

ответ

4

Это не полезно, если ваш класс полностью полагается на __getstate__/__setstate__ для травления.

Как документы на __setstate__ объяснить:

После unpickling, если класс определяет __setstate__(), она вызывается с несорванным состоянием ... Если __getstate__() возвращает ложное значение, то метод __setstate__() не будет вызываться при unpicking ,

Так что, если ваши __getstate__ возвращается None, он не будет принят обратно к вам в __setstate__ время; вы просто не будете вызваны.

Однако обратите внимание на то, что в 2.x version это не относится к классическим классам. С классическим классом «Если класс определяет как __getstate__(), так и __setstate__(), объект состояния не обязательно должен быть словарем, и эти методы могут делать то, что они хотят». (На самом деле, я считаю, что есть случаи, когда любое значение ложности превращается в {}, что не очень хорошо документировано, но то же самое заявление if обрабатывает это ...)

По-прежнему, это не объясняет, зачем вам нужно значение по умолчанию ... Если вы можете получить None, обязательно, вам нужно написать код, который имеет дело с None ... но вам не нужно писать код, который не получает параметр вообще, не так ли?

Но есть причины, по которым вы можете это сделать.

Во-первых, обратите внимание, что этот класс __setstate__ этого класса делает больше, чем обычно: он инициализирует «сначала от значений по умолчанию, а затем от состояния в реальном времени». Таким образом, было бы очень полезно использовать модульный тест, который инициализирует работу по умолчанию.

Кроме того, если вы определяете настраиваемый метод и нерегенератор __reduce__, нет никаких оснований полагать, что он должен следовать точно таким же правилам, что и нерепреобразователь по умолчанию. Или, конечно, нет причин, по которым он должен называть __setstate__вообще, но если вы, скажем, создаете базовый класс, который вы ожидаете от ваших подклассов, делает ваш unreducer настолько же удобным, как и по умолчанию, поэтому ваши пользователи может просто переопределить __setstate__ вместо того, чтобы добавить свою собственную целую реализацию __reduce__.

Точно так же, если вы строите свой собственный сериалайзер на вершине pickle/copyreg, а не просто использовать его как есть, ваш код не должен использовать те же правила, как pickle. Опять же, нет причин, по которым он должен использовать даже аналогичные правила, но это может значительно облегчить для ваших пользователей расширение ваших классов.

Независимо от того, относится ли это к serge, я понятия не имею, но это обе вещи, которые могут легко применяться к широкому спектру типов, которые вы, возможно, захотите построить.

+0

Фантастический ответ, только то, что я искал. Спасибо! – user3002473

+0

@ user3002473: Обязательно прочитайте отредактированную версию для бит классических классов, о которой я сначала забыл ... – abarnert

+0

Ahhhh, который много объясняет, так как, если я не ошибаюсь, версию serge, которую я читал был построен для python 2.x (версия serge 0.4.2) – user3002473

Смежные вопросы