Why isnt Pickle calling __new__ like the documentation says?

2024/11/17 3:09:48

The documentation for Pickle specifically says:

Instances of a new-style class C are created using:

obj = C.__new__(C, *args)

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

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

(This class is used in a caching layer to differentiate a no-result result from nothing in the cache.)

The singleton works great (every call to ZeroResultSentinel() results in the same instance in memory, and ZeroResultSentinel() == ZeroResultSentinel() evaluates to True). And I can pickle and unpickle the instance without errors. However, when I unpickle it, I get a different instance. So I placed a breakpoint within __new__. I hit the breakpoint every time I call ZeroResultSentinel(), but I do not hit a breakpoint when I unpickle a pickled ZeroResultSentinel. This is in direct contradiction to the documentation. So am I doing something wrong, or is the documentation incorrect?

Answer

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

>>> 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>

On Python 2, the default protocol is 0, so if you're using the default, you'll have to change that.

https://en.xdnf.cn/q/71596.html

Related Q&A

Remove more than one key from Python dict

Is there any efficient shortcut method to delete more than one key at a time from a python dictionary?For instance;x = {a: 5, b: 2, c: 3} x.pop(a, b) print x {c: 3}

Install poppler in AWS base python image for Lambda

I am trying to deploy my docker container on AWS Lambda. However, I use pdf2image package in my code which depends on poppler. To install poppler, I need to insert the following line in the Dockerfile.…

Cant change state of checkable QListViewItem with custom widget

I have a QListWidget where I want to add a bunch of items with a custom widget:listWidget = QListWidget()item = QListWidgetItem()item.setFlags(item.flags() | Qt.ItemIsUserCheckable)item.setCheckState(Q…

Custom table for str.translate in Python 3

If I run this code:s.translate(str.maketrans({as: dfg, 1234: qw}))I will get:ValueError: string keys in translate table must be of length 1Is there a way to replace multiple characters at once using st…

Sending form data to aspx page

There is a need to do a search on the websiteurl = rhttp://www.cpso.on.ca/docsearch/this is an aspx page (Im beginning this trek as of yesterday, sorry for noob questions)using BeautifulSoup, I can get…

What is the difference between imregionalmax() of matlab and scipy.ndimage.filters.maximum_filter

I need to find the regional maxima of an image to obtain foreground markers for watershed segmentation. I see in matlab use the function imregionalmax(). As I dont have the matlab software, I use the f…

crontab: python script being run but does not execute OS Commands

I have this crontab configuration setup and the following script.MAILTO="[email protected]" 41 15 * * * /usr/bin/python /home/atweb/Documents/opengrok/setup_and_restart.py > /home/at…

concatenating arrays in python like matlab without knowing the size of the output array

I am trying to concatenate arrays in python similar to matlab array1= zeros(3,500); array2=ones(3,700); array=[array1, array2];I did the following in python:array1=np.zeros((3,500)) array2=np.ones((3,7…

How to save the result of a comparison using Djangos with template tag?

I would like to create new variable in django template, which will have a value of comparison obj.site.profile.default_role == objUnfortunately none of this code works: {% with obj.site.profile.default…

How to merge two list of dictionaries based on a value

I have two lists of dictionaries, lets say: a = [{id: 1, name: a}] b = [{id: 1, city: b}]I want to have a list that merges every dictionary in both lists with the same ID. In this example i expect to h…