Why doesn't Pickle call __new__, as the documentation says?

The documentation for Pickle specifically says:

Class C instances of the new style are created using:

obj = C.__new__(C, *args) 

Trying to take advantage of this, I created a singleton with no attributes or instance methods:

 class ZeroResultSentinel(object): instance = None def __new__(cls, *args): if not cls.instance: cls.instance = super(ZeroResultSentinel, cls).__new__(cls, *args) return cls.instance 

(This class is used in the cache layer to distinguish a result without a result from nothing in the cache.)

Singleton works fine (every call to ZeroResultSentinel() leads to the same instance in memory, and ZeroResultSentinel() == ZeroResultSentinel() - True ). And I can sort and print the instance without errors. However, when I unpack it, I get another instance. So I set a breakpoint in __new__ . I hit a breakpoint every time I call ZeroResultSentinel() , but I don't hit a breakpoint when I scatter the pickled ZeroResultSentinel . This directly contradicts the documentation. So am I doing something wrong, or is the documentation incorrect?

+5
source share
1 answer

The documentation doesn't really make it clear, but your __new__ method will only be used for pickle 2 protocol and above:

 >>> class Foo(object): ... def __new__(cls): ... print "New" ... return object.__new__(cls) ... >>> foo = Foo() New >>> pickle.loads(pickle.dumps(foo, protocol=0)) <__main__.Foo object at 0x00000000025E9A20> >>> pickle.loads(pickle.dumps(foo, protocol=2)) New <__main__.Foo object at 0x00000000022A3F60> 

Python 2 uses protocol 0 by default, so if you use the default, you will have to change this.

+3
source

Source: https://habr.com/ru/post/1247290/


All Articles