Factory for unique objects

Factory for unique objects

More general than unique_representation, the UniqueFactory class can specify a subset of the arguments that serve as the unique key. Typically, this is used to construct objects that accept an optional check=[True|False] argument, but whose result should be unique irregardless of said optional argument.

class sage.structure.factory.UniqueFactory

Bases: sage.structure.sage_object.SageObject

This class is intended to make it easy to make unique, cached objects.

It is based on the idea that the object is uniquely defined by a set of defining data (the key). There is also the possibility some non-defining data (extra args) which will be used in initial creation, but not affect the caching.

The objects created are cached (using weakrefs) based on their key and returned directly rather than re-created if requested again. Pickling will return the same object for the same version of Sage, and distinct (but hopefully equal) objects for different versions of Sage.

Typically one only needs to implement create_key() and create_object().

create_key(*args, **kwds)

Given the arguments and keywords, create a key that uniquely determines this object.

EXAMPLES:

sage: from sage.structure.test_factory import test_factory
sage: test_factory.create_key(1, 2, key=5)
(1, 2)
create_key_and_extra_args(*args, **kwds)

Return a tuple containing the key (uniquely defining data) and any extra arguments (empty by default).

Defaults to create_key().

EXAMPLES:

sage: from sage.structure.test_factory import test_factory
sage: test_factory.create_key_and_extra_args(1, 2, key=5)
((1, 2), {})
sage: GF.create_key_and_extra_args(3, foo='value')
((3, None, None, None, "{'foo': 'value'}", 3, 1, True), {'foo': 'value'})
create_object(version, key, **extra_args)

Create the object from the key and extra arguments. This is only called if the object was not found in the cache.

EXAMPLES:

sage: from sage.structure.test_factory import test_factory
sage: test_factory.create_object(0, (1,2,3))
Making object (1, 2, 3)
<sage.structure.test_factory.A instance at ...>
sage: test_factory('a')
Making object ('a',)
<sage.structure.test_factory.A instance at ...>
sage: test_factory('a') # NOT called again
<sage.structure.test_factory.A instance at ...>
get_object(version, key, extra_args)

Returns the object corresponding to key, creating it with extra_args if necessary (for example, it isn’t in the cache or it is unpickling from an older version of Sage).

EXAMPLES:

sage: from sage.structure.test_factory import test_factory
sage: a = test_factory.get_object(3.0, 'a', {}); a
Making object a
<sage.structure.test_factory.A instance at ...>
sage: test_factory.get_object(3.0, 'a', {}) is test_factory.get_object(3.0, 'a', {})
True
sage: test_factory.get_object(3.0, 'a', {}) is test_factory.get_object(3.1, 'a', {})
Making object a
False
sage: test_factory.get_object(3.0, 'a', {}) is test_factory.get_object(3.0, 'b', {})
Making object b
False
get_version(sage_version)

This is provided to allow more or less granular control over pickle versioning. Objects pickled in the same version of Sage will unpickle to the same rather than simply equal objects. This can provide significant gains as arithmetic must be performed on objects with identical parents. However, if there has been an incompatible change (e.g. in element representation) we want the version number to change so coercion is forced between the two parents.

Defaults to the Sage version that is passed in, but courser granularity can be provided.

EXAMPLES:

sage: from sage.structure.test_factory import test_factory
sage: test_factory.get_version((3,1,0))
(3, 1, 0)
other_keys(key, obj)

Sometimes during object creation, certain defaults are chosen which may result in a new (more specific) key. This allows the more specific key to be cached as well, and used for pickling.

EXAMPLES:

sage: key, _ = GF.create_key_and_extra_args(27, 'k'); key
(27, ('k',), x^3 + 2*x + 1, None, '{}', 3, 3, True)
sage: K = GF.create_object(0, key); K
Finite Field in k of size 3^3
sage: GF.other_keys(key, K)
[(27, ('k',), x^3 + 2*x + 1, None, '{}', 3, 3, True),
 (27, ('k',), x^3 + 2*x + 1, 'givaro', '{}', 3, 3, True)]

sage: K = GF(7^40, 'a')
sage: loads(dumps(K)) is K
True
reduce_data(obj)

The results of this function can be returned from __reduce__(). This is here so the factory internals can change without having to re-write __reduce__() methods that use it.

EXAMPLE:

sage: V = FreeModule(ZZ, 5)
sage: factory, data = FreeModule.reduce_data(V)
sage: factory(*data)
Ambient free module of rank 5 over the principal ideal domain Integer Ring
sage: factory(*data) is V
True

sage: from sage.structure.test_factory import test_factory
sage: a = test_factory(1, 2)
Making object (1, 2)
sage: test_factory.reduce_data(a)
(<built-in function generic_factory_unpickle>,
 (<class 'sage.structure.test_factory.UniqueFactoryTester'>,
  (...),
  (1, 2),
  {}))

Note that the ellipsis (...) here stands for the Sage version.

sage.structure.factory.generic_factory_reduce(self, proto)

Used to provide a __reduce__ method if one does not already exist.

EXAMPLES:

sage: V = QQ^6
sage: sage.structure.factory.generic_factory_reduce(V, 1) == V.__reduce_ex__(1)
True
sage.structure.factory.generic_factory_unpickle(factory, *args)

Method used for unpickling the object.

The unpickling mechanism needs a plain Python function to call. It takes a factory as the first argument, passes the rest of the arguments onto the factory’s UniqueFactory.get_object() method.

EXAMPLES:

sage: V = FreeModule(ZZ, 5)
sage: func, data = FreeModule.reduce_data(V)
sage: func is sage.structure.factory.generic_factory_unpickle
True
sage: sage.structure.factory.generic_factory_unpickle(*data) is V
True
sage.structure.factory.lookup_global(name)

Used in unpickling the factory itself.

EXAMPLES:

sage: from sage.structure.factory import lookup_global
sage: lookup_global('ZZ')
Integer Ring
sage: lookup_global('sage.rings.all.ZZ')
Integer Ring

Previous topic

Unique Representation

Next topic

Dynamic classes

This Page