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[source]#
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 usingprovide_hash_by_id()
, but has the advantage that the hash can be prescribed, by assigning a cdef attribute_hash
.
- class sage.misc.fast_methods.Singleton[source]#
Bases:
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
>>> from sage.all import * >>> from sage.misc.fast_methods import Singleton >>> class C(Singleton, SageObject): ... def __init__(self): ... print("creating singleton") >>> c = C() creating singleton >>> c2 = C() >>> 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'>
>>> from sage.all import * >>> class D(C): ... pass >>> import __main__ # This is only needed ... >>> __main__.C = C # ... in doctests >>> __main__.D = D # same here, only in doctests >>> orig = type(c) >>> c.__class__ = D >>> orig == type(c) False >>> 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 sage.misc.fast_methods.WithEqualityById[source]#
Bases:
object
Provide hash and equality test based on identity.
Note
This class provides the unique representation behaviour of
UniqueRepresentation
, together withCachedRepresentation
.EXAMPLES:
Any instance of
UniqueRepresentation
inherits fromWithEqualityById
.sage: class MyParent(Parent): ....: def __init__(self, x): ....: self.x = x ....: def __hash__(self): ....: return hash(self.x) sage: class MyUniqueParent(UniqueRepresentation, MyParent): pass sage: issubclass(MyUniqueParent, sage.misc.fast_methods.WithEqualityById) True
>>> from sage.all import * >>> class MyParent(Parent): ... def __init__(self, x): ... self.x = x ... def __hash__(self): ... return hash(self.x) >>> class MyUniqueParent(UniqueRepresentation, MyParent): pass >>> issubclass(MyUniqueParent, sage.misc.fast_methods.WithEqualityById) True
Inheriting from
WithEqualityById
provides unique representation behaviour: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
>>> from sage.all import * >>> a = MyUniqueParent(Integer(1)) >>> b = MyUniqueParent(Integer(2)) >>> c = MyUniqueParent(Integer(1)) >>> a is c True >>> d = MyUniqueParent(-Integer(1)) >>> a == d False
The hash inherited from
MyParent
is replaced by a hash that coincides withobject
’s hash:sage: hash(a) == hash(a.x) False sage: hash(a) == object.__hash__(a) True
>>> from sage.all import * >>> hash(a) == hash(a.x) False >>> 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 useCachedRepresentation
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
>>> from sage.all import * >>> class MyNonUniqueParent(MyUniqueParent): ... def __eq__(self, other): ... return self.x**Integer(2) == other.x**Integer(2) >>> a = MyNonUniqueParent(Integer(1)) >>> d = MyNonUniqueParent(-Integer(1)) >>> a is MyNonUniqueParent(Integer(1)) True >>> a == d True >>> a is d False