/* Using a cache is very effective since typically only a single slice is
created and then deleted again. */
PySliceObject *slice_cache;
- // The empty frozenset is a singleton.
- PyObject *empty_frozenset;
struct _Py_tuple_state tuple;
struct _Py_list_state list;
extern void _PyDict_Fini(PyThreadState *tstate);
extern void _PyTuple_Fini(PyThreadState *tstate);
extern void _PyList_Fini(PyThreadState *tstate);
-extern void _PySet_Fini(PyThreadState *tstate);
extern void _PyBytes_Fini(PyThreadState *tstate);
extern void _PyFloat_Fini(PyThreadState *tstate);
extern void _PySlice_Fini(PyThreadState *tstate);
for constructor in (set, frozenset):
self.helper(constructor(self.d.keys()))
- @support.cpython_only
- def test_empty_frozenset_singleton(self):
- # marshal.loads() must reuse the empty frozenset singleton
- obj = frozenset()
- obj2 = marshal.loads(marshal.dumps(obj))
- self.assertIs(obj2, obj)
-
class BufferTestCase(unittest.TestCase, HelperMixin):
s.__init__(self.otherword)
self.assertEqual(s, set(self.word))
- def test_singleton_empty_frozenset(self):
- f = frozenset()
- efs = [frozenset(), frozenset([]), frozenset(()), frozenset(''),
- frozenset(), frozenset([]), frozenset(()), frozenset(''),
- frozenset(range(0)), frozenset(frozenset()),
- frozenset(f), f]
- # All of the empty frozensets should have just one id()
- self.assertEqual(len(set(map(id, efs))), 1)
-
def test_constructor_identity(self):
s = self.thetype(range(3))
t = self.thetype(s)
* Free lists: float, tuple, list, dict, frame, context,
asynchronous generator.
-* Singletons: empty tuple, empty frozenset, empty bytes string,
+* Singletons: empty tuple, empty bytes string,
single byte character.
* Slice cache.
They are no longer shared by all interpreters.
+
--- /dev/null
+Empty frozensets are no longer singletons.
static PyObject *
make_new_frozenset(PyTypeObject *type, PyObject *iterable)
{
- PyObject *res;
-
if (type != &PyFrozenSet_Type) {
return make_new_set(type, iterable);
}
- if (iterable != NULL) {
- if (PyFrozenSet_CheckExact(iterable)) {
- /* frozenset(f) is idempotent */
- Py_INCREF(iterable);
- return iterable;
- }
- res = make_new_set((PyTypeObject *)type, iterable);
- if (res == NULL || PySet_GET_SIZE(res) != 0) {
- return res;
- }
- /* If the created frozenset is empty, return the empty frozenset singleton instead */
- Py_DECREF(res);
+ if (iterable != NULL && PyFrozenSet_CheckExact(iterable)) {
+ /* frozenset(f) is idempotent */
+ Py_INCREF(iterable);
+ return iterable;
}
-
- // The empty frozenset is a singleton
- PyInterpreterState *interp = _PyInterpreterState_GET();
- res = interp->empty_frozenset;
- if (res == NULL) {
- interp->empty_frozenset = make_new_set((PyTypeObject *)type, NULL);
- res = interp->empty_frozenset;
- if (res == NULL) {
- return NULL;
- }
- }
- Py_INCREF(res);
- return res;
+ return make_new_set((PyTypeObject *)type, iterable);
}
static PyObject *
return set_add_key((PySetObject *)anyset, key);
}
-void
-_PySet_Fini(PyThreadState *tstate)
-{
- Py_CLEAR(tstate->interp->empty_frozenset);
-}
-
int
_PySet_NextEntry(PyObject *set, Py_ssize_t *pos, PyObject **key, Py_hash_t *hash)
{
_PyAsyncGen_Fini(tstate);
_PyContext_Fini(tstate);
- _PySet_Fini(tstate);
_PyDict_Fini(tstate);
_PyList_Fini(tstate);
_PyTuple_Fini(tstate);