Fast methods via Cython

This module provides extension classes with useful methods of cython speed, that python classes can inherit.

Note

This module provides a cython base class WithEqualityById implementing unique instance behaviour, and a cython base class FastHashable_class, which has a quite fast hash whose value can be freely chosen at initialisation time.

AUTHOR:

  • Simon King (2013-02): Original version
  • Simon King (2013-10): Add Singleton
class sage.misc.fast_methods.FastHashable_class

Bases: object

A class that has a fast hash method, returning a pre-assigned value.

NOTE:

This is for internal use only. The class has a cdef attribute _hash, that needs to be assigned (for example, by calling the init method, or by a direct assignement using cython). This is slower than using provide_hash_by_id(), but has the advantage that the hash can be prescribed, by assigning a cdef attribute _hash.

TESTS:

sage: from sage.misc.fast_methods import FastHashable_class
sage: H = FastHashable_class(123)
sage: hash(H)
123
class sage.misc.fast_methods.Singleton

Bases: sage.misc.fast_methods.WithEqualityById

A base class for singletons.

A singleton is a class that allows to create not more than a single instance. This instance can also belong to a subclass, but it is not possible to have several subclasses of a singleton all having distinct unique instances.

In order to create a singleton, just add Singleton to the list of base classes:

sage: from sage.misc.fast_methods import Singleton
sage: class C(Singleton, SageObject):
....:     def __init__(self):
....:         print "creating singleton"
sage: c = C()
creating singleton
sage: c2 = C()
sage: c is c2
True

The unique instance of a singleton stays in memory as long as the singleton itself does.

Pickling, copying, hashing, and comparison are provided for by Singleton according to the singleton paradigm. Note that pickling fails if the class is replaced by a sub-sub-class after creation of the instance:

sage: class D(C):
....:     pass
sage: import __main__      # This is only needed ...
sage: __main__.C = C       # ... in doctests
sage: __main__.D = D       # same here, only in doctests
sage: orig = type(c)
sage: c.__class__ = D
sage: orig == type(c)
False
sage: loads(dumps(c))
Traceback (most recent call last):
...
AssertionError: (("<class '__main__.D'> is not a direct
subclass of <class 'sage.misc.fast_methods.Singleton'>",),
<class '__main__.D'>, ())
class sage.misc.fast_methods.WithEqualityById

Bases: object

Provide hash and equality test based on identity.

Note

This class provides the unique representation behaviour of UniqueRepresentation, together with CachedRepresentation.

EXAMPLES:

Any instance of UniqueRepresentation inherits from WithEqualityById.

sage: class MyParent(Parent):
...     def __init__(self, x):
...         self.x = x
...     def __cmp__(self,other):
...         return cmp(self.x^2,other.x^2)
...     def __hash__(self):
...         return hash(self.x)
sage: class MyUniqueParent(UniqueRepresentation, MyParent): pass
sage: issubclass(MyUniqueParent, sage.misc.fast_methods.WithEqualityById)
True

Inheriting from WithEqualityById provides unique representation behaviour. In particular, the comparison inherited from MyParent is overloaded:

sage: a = MyUniqueParent(1)
sage: b = MyUniqueParent(2)
sage: c = MyUniqueParent(1)
sage: a is c
True
sage: d = MyUniqueParent(-1)
sage: a == d
False

Note, however, that Python distinguishes between “comparison by cmp” and “comparison by binary relations”:

sage: cmp(a,d)
0

The comparison inherited from MyParent will be used in those cases in which identity does not give sufficient information to find the relation:

sage: a < b
True
sage: b > d
True

The hash inherited from MyParent is replaced by a hash that coincides with object‘s hash:

sage: hash(a) == hash(a.x)
False
sage: hash(a) == object.__hash__(a)
True

Warning

It is possible to inherit from UniqueRepresentation and then overload equality test in a way that destroys the unique representation property. We strongly recommend against it! You should use CachedRepresentation instead.

sage: class MyNonUniqueParent(MyUniqueParent):
...     def __eq__(self, other):
...         return self.x^2 == other.x^2
sage: a = MyNonUniqueParent(1)
sage: d = MyNonUniqueParent(-1)
sage: a is MyNonUniqueParent(1)
True
sage: a == d
True
sage: a is d
False

Previous topic

Special Methods for Classes

Next topic

Unit testing for Sage objects

This Page