passagemath-objects 10.6.45__cp313-cp313-musllinux_1_2_x86_64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of passagemath-objects might be problematic. Click here for more details.

Files changed (280) hide show
  1. passagemath_objects/__init__.py +3 -0
  2. passagemath_objects-10.6.45.dist-info/METADATA +115 -0
  3. passagemath_objects-10.6.45.dist-info/RECORD +280 -0
  4. passagemath_objects-10.6.45.dist-info/WHEEL +5 -0
  5. passagemath_objects-10.6.45.dist-info/top_level.txt +3 -0
  6. passagemath_objects.libs/libgmp-0e7fc84e.so.10.5.0 +0 -0
  7. sage/all__sagemath_objects.py +37 -0
  8. sage/arith/all__sagemath_objects.py +5 -0
  9. sage/arith/long.pxd +411 -0
  10. sage/arith/numerical_approx.cpython-313-x86_64-linux-musl.so +0 -0
  11. sage/arith/numerical_approx.pxd +35 -0
  12. sage/arith/numerical_approx.pyx +75 -0
  13. sage/arith/power.cpython-313-x86_64-linux-musl.so +0 -0
  14. sage/arith/power.pxd +31 -0
  15. sage/arith/power.pyx +127 -0
  16. sage/categories/action.cpython-313-x86_64-linux-musl.so +0 -0
  17. sage/categories/action.pxd +29 -0
  18. sage/categories/action.pyx +641 -0
  19. sage/categories/algebra_functor.py +745 -0
  20. sage/categories/all__sagemath_objects.py +33 -0
  21. sage/categories/basic.py +62 -0
  22. sage/categories/cartesian_product.py +295 -0
  23. sage/categories/category.py +3401 -0
  24. sage/categories/category_cy_helper.cpython-313-x86_64-linux-musl.so +0 -0
  25. sage/categories/category_cy_helper.pxd +8 -0
  26. sage/categories/category_cy_helper.pyx +322 -0
  27. sage/categories/category_singleton.cpython-313-x86_64-linux-musl.so +0 -0
  28. sage/categories/category_singleton.pxd +3 -0
  29. sage/categories/category_singleton.pyx +342 -0
  30. sage/categories/category_types.py +637 -0
  31. sage/categories/category_with_axiom.py +2876 -0
  32. sage/categories/covariant_functorial_construction.py +703 -0
  33. sage/categories/facade_sets.py +228 -0
  34. sage/categories/functor.cpython-313-x86_64-linux-musl.so +0 -0
  35. sage/categories/functor.pxd +7 -0
  36. sage/categories/functor.pyx +691 -0
  37. sage/categories/homset.py +1338 -0
  38. sage/categories/homsets.py +364 -0
  39. sage/categories/isomorphic_objects.py +73 -0
  40. sage/categories/map.cpython-313-x86_64-linux-musl.so +0 -0
  41. sage/categories/map.pxd +34 -0
  42. sage/categories/map.pyx +2106 -0
  43. sage/categories/morphism.cpython-313-x86_64-linux-musl.so +0 -0
  44. sage/categories/morphism.pxd +14 -0
  45. sage/categories/morphism.pyx +895 -0
  46. sage/categories/objects.py +167 -0
  47. sage/categories/primer.py +1696 -0
  48. sage/categories/pushout.py +4834 -0
  49. sage/categories/quotients.py +64 -0
  50. sage/categories/realizations.py +200 -0
  51. sage/categories/sets_cat.py +3290 -0
  52. sage/categories/sets_with_partial_maps.py +52 -0
  53. sage/categories/subobjects.py +64 -0
  54. sage/categories/subquotients.py +21 -0
  55. sage/categories/with_realizations.py +311 -0
  56. sage/cpython/__init__.py +19 -0
  57. sage/cpython/_py2_random.py +619 -0
  58. sage/cpython/all.py +3 -0
  59. sage/cpython/atexit.cpython-313-x86_64-linux-musl.so +0 -0
  60. sage/cpython/atexit.pyx +269 -0
  61. sage/cpython/builtin_types.cpython-313-x86_64-linux-musl.so +0 -0
  62. sage/cpython/builtin_types.pyx +7 -0
  63. sage/cpython/cython_metaclass.cpython-313-x86_64-linux-musl.so +0 -0
  64. sage/cpython/cython_metaclass.h +117 -0
  65. sage/cpython/cython_metaclass.pxd +3 -0
  66. sage/cpython/cython_metaclass.pyx +130 -0
  67. sage/cpython/debug.cpython-313-x86_64-linux-musl.so +0 -0
  68. sage/cpython/debug.pyx +302 -0
  69. sage/cpython/dict_del_by_value.cpython-313-x86_64-linux-musl.so +0 -0
  70. sage/cpython/dict_del_by_value.pxd +9 -0
  71. sage/cpython/dict_del_by_value.pyx +191 -0
  72. sage/cpython/dict_internal.h +245 -0
  73. sage/cpython/getattr.cpython-313-x86_64-linux-musl.so +0 -0
  74. sage/cpython/getattr.pxd +9 -0
  75. sage/cpython/getattr.pyx +439 -0
  76. sage/cpython/pycore_long.h +97 -0
  77. sage/cpython/pycore_long.pxd +10 -0
  78. sage/cpython/python_debug.h +44 -0
  79. sage/cpython/python_debug.pxd +47 -0
  80. sage/cpython/pyx_visit.h +13 -0
  81. sage/cpython/string.cpython-313-x86_64-linux-musl.so +0 -0
  82. sage/cpython/string.pxd +76 -0
  83. sage/cpython/string.pyx +34 -0
  84. sage/cpython/string_impl.h +60 -0
  85. sage/cpython/type.cpython-313-x86_64-linux-musl.so +0 -0
  86. sage/cpython/type.pxd +2 -0
  87. sage/cpython/type.pyx +40 -0
  88. sage/cpython/wrapperdescr.pxd +67 -0
  89. sage/ext/all__sagemath_objects.py +3 -0
  90. sage/ext/ccobject.h +64 -0
  91. sage/ext/cplusplus.pxd +17 -0
  92. sage/ext/mod_int.h +30 -0
  93. sage/ext/mod_int.pxd +24 -0
  94. sage/ext/stdsage.pxd +39 -0
  95. sage/groups/all__sagemath_objects.py +1 -0
  96. sage/groups/group.cpython-313-x86_64-linux-musl.so +0 -0
  97. sage/groups/group.pxd +14 -0
  98. sage/groups/group.pyx +322 -0
  99. sage/groups/old.cpython-313-x86_64-linux-musl.so +0 -0
  100. sage/groups/old.pxd +14 -0
  101. sage/groups/old.pyx +219 -0
  102. sage/libs/all__sagemath_objects.py +3 -0
  103. sage/libs/gmp/__init__.py +1 -0
  104. sage/libs/gmp/all.pxd +6 -0
  105. sage/libs/gmp/binop.pxd +23 -0
  106. sage/libs/gmp/misc.pxd +8 -0
  107. sage/libs/gmp/mpf.pxd +88 -0
  108. sage/libs/gmp/mpn.pxd +57 -0
  109. sage/libs/gmp/mpq.pxd +57 -0
  110. sage/libs/gmp/mpz.pxd +202 -0
  111. sage/libs/gmp/pylong.cpython-313-x86_64-linux-musl.so +0 -0
  112. sage/libs/gmp/pylong.pxd +12 -0
  113. sage/libs/gmp/pylong.pyx +150 -0
  114. sage/libs/gmp/random.pxd +25 -0
  115. sage/libs/gmp/randomize.pxd +59 -0
  116. sage/libs/gmp/types.pxd +53 -0
  117. sage/libs/gmpxx.pxd +19 -0
  118. sage/misc/abstract_method.py +276 -0
  119. sage/misc/all__sagemath_objects.py +43 -0
  120. sage/misc/bindable_class.py +253 -0
  121. sage/misc/c3_controlled.cpython-313-x86_64-linux-musl.so +0 -0
  122. sage/misc/c3_controlled.pxd +2 -0
  123. sage/misc/c3_controlled.pyx +1402 -0
  124. sage/misc/cachefunc.cpython-313-x86_64-linux-musl.so +0 -0
  125. sage/misc/cachefunc.pxd +43 -0
  126. sage/misc/cachefunc.pyx +3781 -0
  127. sage/misc/call.py +188 -0
  128. sage/misc/classcall_metaclass.cpython-313-x86_64-linux-musl.so +0 -0
  129. sage/misc/classcall_metaclass.pxd +14 -0
  130. sage/misc/classcall_metaclass.pyx +599 -0
  131. sage/misc/constant_function.cpython-313-x86_64-linux-musl.so +0 -0
  132. sage/misc/constant_function.pyx +130 -0
  133. sage/misc/decorators.py +747 -0
  134. sage/misc/fast_methods.cpython-313-x86_64-linux-musl.so +0 -0
  135. sage/misc/fast_methods.pxd +20 -0
  136. sage/misc/fast_methods.pyx +351 -0
  137. sage/misc/flatten.py +90 -0
  138. sage/misc/fpickle.cpython-313-x86_64-linux-musl.so +0 -0
  139. sage/misc/fpickle.pyx +177 -0
  140. sage/misc/function_mangling.cpython-313-x86_64-linux-musl.so +0 -0
  141. sage/misc/function_mangling.pxd +11 -0
  142. sage/misc/function_mangling.pyx +308 -0
  143. sage/misc/inherit_comparison.cpython-313-x86_64-linux-musl.so +0 -0
  144. sage/misc/inherit_comparison.pxd +5 -0
  145. sage/misc/inherit_comparison.pyx +105 -0
  146. sage/misc/instancedoc.cpython-313-x86_64-linux-musl.so +0 -0
  147. sage/misc/instancedoc.pyx +331 -0
  148. sage/misc/lazy_attribute.cpython-313-x86_64-linux-musl.so +0 -0
  149. sage/misc/lazy_attribute.pyx +607 -0
  150. sage/misc/lazy_format.py +135 -0
  151. sage/misc/lazy_import.cpython-313-x86_64-linux-musl.so +0 -0
  152. sage/misc/lazy_import.pyx +1299 -0
  153. sage/misc/lazy_import_cache.py +36 -0
  154. sage/misc/lazy_list.cpython-313-x86_64-linux-musl.so +0 -0
  155. sage/misc/lazy_list.pxd +19 -0
  156. sage/misc/lazy_list.pyx +1187 -0
  157. sage/misc/lazy_string.cpython-313-x86_64-linux-musl.so +0 -0
  158. sage/misc/lazy_string.pxd +7 -0
  159. sage/misc/lazy_string.pyx +546 -0
  160. sage/misc/misc.py +1066 -0
  161. sage/misc/misc_c.cpython-313-x86_64-linux-musl.so +0 -0
  162. sage/misc/misc_c.pxd +3 -0
  163. sage/misc/misc_c.pyx +766 -0
  164. sage/misc/namespace_package.py +37 -0
  165. sage/misc/nested_class.cpython-313-x86_64-linux-musl.so +0 -0
  166. sage/misc/nested_class.pxd +3 -0
  167. sage/misc/nested_class.pyx +394 -0
  168. sage/misc/persist.cpython-313-x86_64-linux-musl.so +0 -0
  169. sage/misc/persist.pyx +1251 -0
  170. sage/misc/prandom.py +418 -0
  171. sage/misc/randstate.cpython-313-x86_64-linux-musl.so +0 -0
  172. sage/misc/randstate.pxd +30 -0
  173. sage/misc/randstate.pyx +1059 -0
  174. sage/misc/repr.py +203 -0
  175. sage/misc/reset.cpython-313-x86_64-linux-musl.so +0 -0
  176. sage/misc/reset.pyx +196 -0
  177. sage/misc/sage_ostools.cpython-313-x86_64-linux-musl.so +0 -0
  178. sage/misc/sage_ostools.pyx +323 -0
  179. sage/misc/sage_timeit.py +275 -0
  180. sage/misc/sage_timeit_class.cpython-313-x86_64-linux-musl.so +0 -0
  181. sage/misc/sage_timeit_class.pyx +120 -0
  182. sage/misc/sage_unittest.py +637 -0
  183. sage/misc/sageinspect.py +2768 -0
  184. sage/misc/session.cpython-313-x86_64-linux-musl.so +0 -0
  185. sage/misc/session.pyx +392 -0
  186. sage/misc/superseded.py +557 -0
  187. sage/misc/test_nested_class.py +228 -0
  188. sage/misc/timing.py +264 -0
  189. sage/misc/unknown.py +222 -0
  190. sage/misc/verbose.py +253 -0
  191. sage/misc/weak_dict.cpython-313-x86_64-linux-musl.so +0 -0
  192. sage/misc/weak_dict.pxd +15 -0
  193. sage/misc/weak_dict.pyx +1231 -0
  194. sage/modules/all__sagemath_objects.py +1 -0
  195. sage/modules/module.cpython-313-x86_64-linux-musl.so +0 -0
  196. sage/modules/module.pxd +5 -0
  197. sage/modules/module.pyx +329 -0
  198. sage/rings/all__sagemath_objects.py +3 -0
  199. sage/rings/integer_fake.h +22 -0
  200. sage/rings/integer_fake.pxd +55 -0
  201. sage/sets/all__sagemath_objects.py +3 -0
  202. sage/sets/pythonclass.cpython-313-x86_64-linux-musl.so +0 -0
  203. sage/sets/pythonclass.pxd +9 -0
  204. sage/sets/pythonclass.pyx +247 -0
  205. sage/structure/__init__.py +4 -0
  206. sage/structure/all.py +30 -0
  207. sage/structure/category_object.cpython-313-x86_64-linux-musl.so +0 -0
  208. sage/structure/category_object.pxd +28 -0
  209. sage/structure/category_object.pyx +1087 -0
  210. sage/structure/coerce.cpython-313-x86_64-linux-musl.so +0 -0
  211. sage/structure/coerce.pxd +44 -0
  212. sage/structure/coerce.pyx +2107 -0
  213. sage/structure/coerce_actions.cpython-313-x86_64-linux-musl.so +0 -0
  214. sage/structure/coerce_actions.pxd +27 -0
  215. sage/structure/coerce_actions.pyx +988 -0
  216. sage/structure/coerce_dict.cpython-313-x86_64-linux-musl.so +0 -0
  217. sage/structure/coerce_dict.pxd +51 -0
  218. sage/structure/coerce_dict.pyx +1557 -0
  219. sage/structure/coerce_exceptions.py +23 -0
  220. sage/structure/coerce_maps.cpython-313-x86_64-linux-musl.so +0 -0
  221. sage/structure/coerce_maps.pxd +28 -0
  222. sage/structure/coerce_maps.pyx +718 -0
  223. sage/structure/debug_options.cpython-313-x86_64-linux-musl.so +0 -0
  224. sage/structure/debug_options.pxd +6 -0
  225. sage/structure/debug_options.pyx +54 -0
  226. sage/structure/dynamic_class.py +541 -0
  227. sage/structure/element.cpython-313-x86_64-linux-musl.so +0 -0
  228. sage/structure/element.pxd +272 -0
  229. sage/structure/element.pyx +4772 -0
  230. sage/structure/element_wrapper.cpython-313-x86_64-linux-musl.so +0 -0
  231. sage/structure/element_wrapper.pxd +12 -0
  232. sage/structure/element_wrapper.pyx +582 -0
  233. sage/structure/factorization.py +1422 -0
  234. sage/structure/factorization_integer.py +105 -0
  235. sage/structure/factory.cpython-313-x86_64-linux-musl.so +0 -0
  236. sage/structure/factory.pyx +786 -0
  237. sage/structure/formal_sum.py +489 -0
  238. sage/structure/gens_py.py +73 -0
  239. sage/structure/global_options.py +1743 -0
  240. sage/structure/indexed_generators.py +863 -0
  241. sage/structure/list_clone.cpython-313-x86_64-linux-musl.so +0 -0
  242. sage/structure/list_clone.pxd +65 -0
  243. sage/structure/list_clone.pyx +1867 -0
  244. sage/structure/list_clone_demo.cpython-313-x86_64-linux-musl.so +0 -0
  245. sage/structure/list_clone_demo.pyx +248 -0
  246. sage/structure/list_clone_timings.py +179 -0
  247. sage/structure/list_clone_timings_cy.cpython-313-x86_64-linux-musl.so +0 -0
  248. sage/structure/list_clone_timings_cy.pyx +86 -0
  249. sage/structure/mutability.cpython-313-x86_64-linux-musl.so +0 -0
  250. sage/structure/mutability.pxd +21 -0
  251. sage/structure/mutability.pyx +348 -0
  252. sage/structure/nonexact.py +69 -0
  253. sage/structure/parent.cpython-313-x86_64-linux-musl.so +0 -0
  254. sage/structure/parent.pxd +112 -0
  255. sage/structure/parent.pyx +3093 -0
  256. sage/structure/parent_base.cpython-313-x86_64-linux-musl.so +0 -0
  257. sage/structure/parent_base.pxd +13 -0
  258. sage/structure/parent_base.pyx +44 -0
  259. sage/structure/parent_gens.cpython-313-x86_64-linux-musl.so +0 -0
  260. sage/structure/parent_gens.pxd +22 -0
  261. sage/structure/parent_gens.pyx +377 -0
  262. sage/structure/parent_old.cpython-313-x86_64-linux-musl.so +0 -0
  263. sage/structure/parent_old.pxd +25 -0
  264. sage/structure/parent_old.pyx +294 -0
  265. sage/structure/proof/__init__.py +1 -0
  266. sage/structure/proof/all.py +243 -0
  267. sage/structure/proof/proof.py +300 -0
  268. sage/structure/richcmp.cpython-313-x86_64-linux-musl.so +0 -0
  269. sage/structure/richcmp.pxd +213 -0
  270. sage/structure/richcmp.pyx +495 -0
  271. sage/structure/sage_object.cpython-313-x86_64-linux-musl.so +0 -0
  272. sage/structure/sage_object.pxd +3 -0
  273. sage/structure/sage_object.pyx +988 -0
  274. sage/structure/sage_object_test.py +19 -0
  275. sage/structure/sequence.py +937 -0
  276. sage/structure/set_factories.py +1178 -0
  277. sage/structure/set_factories_example.py +527 -0
  278. sage/structure/support_view.py +179 -0
  279. sage/structure/test_factory.py +56 -0
  280. sage/structure/unique_representation.py +1359 -0
@@ -0,0 +1,1359 @@
1
+ # sage_setup: distribution = sagemath-objects
2
+ r"""
3
+ Unique Representation
4
+
5
+ Abstract classes for cached and unique representation behavior.
6
+
7
+ .. SEEALSO::
8
+
9
+ :class:`sage.structure.factory.UniqueFactory`
10
+
11
+ AUTHORS:
12
+
13
+ - Nicolas M. Thiery (2008): Original version.
14
+ - Simon A. King (2013-02): Separate cached and unique representation.
15
+ - Simon A. King (2013-08): Extended documentation.
16
+
17
+
18
+ What is a cached representation?
19
+ ================================
20
+
21
+ Instances of a class have a *cached representation behavior* when several
22
+ instances constructed with the same arguments share the same memory
23
+ representation. For example, calling twice::
24
+
25
+ sage: G = SymmetricGroup(6) # needs sage.groups
26
+ sage: H = SymmetricGroup(6) # needs sage.groups
27
+
28
+ to create the symmetric group on six elements gives back the same
29
+ object::
30
+
31
+ sage: G is H # needs sage.groups
32
+ True
33
+
34
+ This is a standard design pattern. Besides saving memory, it allows for
35
+ sharing cached data (say representation theoretical information about a
36
+ group). And of course a look-up in the cache is faster than the creation of a
37
+ new object.
38
+
39
+ Implementing a cached representation
40
+ ------------------------------------
41
+
42
+ Sage provides two standard ways to create a cached representation:
43
+ :class:`CachedRepresentation` and
44
+ :class:`~sage.structure.factory.UniqueFactory`. Note that, in spite of its
45
+ name, :class:`~sage.structure.factory.UniqueFactory` does not ensure *unique*
46
+ representation behaviour, which will be explained below.
47
+
48
+ Using :class:`CachedRepresentation`
49
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
50
+
51
+ It is often very easy to use :class:`CachedRepresentation`: One simply writes
52
+ a Python class and adds :class:`CachedRepresentation` to the list of base
53
+ classes. If one does so, then the arguments used to create an instance of this
54
+ class will by default also be used as keys for the cache::
55
+
56
+ sage: from sage.structure.unique_representation import CachedRepresentation
57
+ sage: class C(CachedRepresentation):
58
+ ....: def __init__(self, a, b=0):
59
+ ....: self.a = a
60
+ ....: self.b = b
61
+ ....: def __repr__(self):
62
+ ....: return "C(%s, %s)"%(self.a, self.b)
63
+ sage: a = C(1)
64
+ sage: a is C(1)
65
+ True
66
+
67
+ In addition, pickling just works, provided that Python is able to look up the
68
+ class. Hence, in the following two lines, we explicitly put the class into the
69
+ ``__main__`` module. This is needed in doctests, but not in an interactive
70
+ session::
71
+
72
+ sage: import __main__
73
+ sage: __main__.C = C
74
+ sage: loads(dumps(a)) is a
75
+ True
76
+
77
+ Often, this very easy approach is sufficient for applications. However, there
78
+ are some pitfalls. Since the arguments are used for caching, all arguments
79
+ must be hashable, i.e., must be valid as dictionary keys::
80
+
81
+ sage: C((1,2))
82
+ C((1, 2), 0)
83
+ sage: C([1,2])
84
+ Traceback (most recent call last):
85
+ ...
86
+ TypeError: ...unhashable type: 'list'...
87
+
88
+ In addition, equivalent ways of providing the arguments are *not*
89
+ automatically normalised when forming the cache key, and hence different but
90
+ equivalent arguments may yield distinct instances::
91
+
92
+ sage: C(1) is C(1,0)
93
+ False
94
+ sage: C(1) is C(a=1)
95
+ False
96
+ sage: repr(C(1)) == repr(C(a=1))
97
+ True
98
+
99
+ It should also be noted that the arguments are compared by equality, not by
100
+ identity. This is often desired, but can imply subtle problems. For example,
101
+ since ``C(1)`` already is in the cache, and since the unit elements in
102
+ different finite fields are all equal to the integer one, we find::
103
+
104
+ sage: GF(5)(1) == 1 == GF(3)(1)
105
+ True
106
+ sage: C(1) is C(GF(3)(1)) is C(GF(5)(1))
107
+ True
108
+
109
+ But ``C(2)`` is not in the cache, and the number two is not equal in different
110
+ finite fields (i. e., ``GF(5)(2) == GF(3)(2)`` returns as ``False``), even
111
+ though it is equal to the number two in the ring of integers (
112
+ ``GF(5)(2) == 2 == GF(3)(2)`` returns as ``True``; equality is not transitive
113
+ when comparing elements of *distinct* algebraic structures!!). Hence, we
114
+ have::
115
+
116
+ sage: GF(5)(2) == GF(3)(2)
117
+ False
118
+ sage: C(GF(3)(2)) is C(GF(5)(2))
119
+ False
120
+
121
+ Normalising the arguments
122
+ .........................
123
+
124
+ :class:`CachedRepresentation` uses the metaclass
125
+ :class:`~sage.misc.classcall_metaclass.ClasscallMetaclass`. Its
126
+ ``__classcall__`` method is a
127
+ :class:`~sage.misc.cachefunc.WeakCachedFunction`. This function creates an
128
+ instance of the given class using the given arguments, unless it finds the
129
+ result in the cache. This has the following implications:
130
+
131
+ - The arguments must be valid dictionary keys (i.e., they must be hashable;
132
+ see above).
133
+ - It is a weak cache, hence, if the user does not keep a reference to the
134
+ resulting instance, then it may be removed from the cache during garbage
135
+ collection.
136
+ - It is possible to preprocess the input arguments by implementing a
137
+ ``__classcall__`` or a ``__classcall_private__`` method, but in order to
138
+ benefit from caching, :meth:`CachedRepresentation.__classcall__` should at
139
+ some point be called.
140
+
141
+ .. NOTE::
142
+
143
+ For technical reasons, it is needed that ``__classcall__`` respectively
144
+ ``__classcall_private__`` are "static methods", i.e., they are callable
145
+ objects that do not bind to an instance or class. For example, a
146
+ :class:`~sage.misc.cachefunc.cached_function` can be used here, because it
147
+ is callable, but does not bind to an instance or class, because it has no
148
+ ``__get__()`` method. A usual Python function, however, has a
149
+ ``__get__()`` method and would thus under normal circumstances bind to an
150
+ instance or class, and thus the instance or class would be passed to the
151
+ function as the first argument. To prevent a callable object from being
152
+ bound to the instance or class, one can prepend the ``@staticmethod``
153
+ decorator to the definition; see :class:`staticmethod`.
154
+
155
+ For more on Python's ``__get__()`` method, see:
156
+ https://docs.python.org/2/howto/descriptor.html
157
+
158
+ .. WARNING::
159
+
160
+ If there is preprocessing, then the preprocessed arguments
161
+ passed to :meth:`CachedRepresentation.__classcall__` must be invariant
162
+ under the preprocessing. That is to say, preprocessing the input
163
+ arguments twice must have the same effect as preprocessing the input
164
+ arguments only once. That is to say, the preprocessing must be idempotent.
165
+
166
+ The reason for this warning lies in the way pickling is implemented. If the
167
+ preprocessed arguments are passed to
168
+ :meth:`CachedRepresentation.__classcall__`, then the resulting instance will
169
+ store the *preprocessed* arguments in some attribute, and will use them for
170
+ pickling. If the pickle is unpickled, then preprocessing is applied to the
171
+ preprocessed arguments---and this second round of preprocessing must not
172
+ change the arguments further, since otherwise a different instance would be
173
+ created.
174
+
175
+ We illustrate the warning by an example. Imagine that one has instances that
176
+ are created with an integer-valued argument, but only depend on the *square*
177
+ of the argument. It would be a mistake to square the given argument during
178
+ preprocessing::
179
+
180
+ sage: class WrongUsage(CachedRepresentation):
181
+ ....: @staticmethod
182
+ ....: def __classcall__(cls, n):
183
+ ....: return super().__classcall__(cls, n^2)
184
+ ....: def __init__(self, n):
185
+ ....: self.n = n
186
+ ....: def __repr__(self):
187
+ ....: return "Something(%d)"%self.n
188
+ sage: import __main__
189
+ sage: __main__.WrongUsage = WrongUsage # This is only needed in doctests
190
+ sage: w = WrongUsage(3); w
191
+ Something(9)
192
+ sage: w._reduction
193
+ (<class '__main__.WrongUsage'>, (9,), {})
194
+
195
+ Indeed, the reduction data are obtained from the preprocessed argument. By
196
+ consequence, if the resulting instance is pickled and unpickled, the argument
197
+ gets squared *again*::
198
+
199
+ sage: loads(dumps(w))
200
+ Something(81)
201
+
202
+ Instead, the preprocessing should only take the absolute value of the given
203
+ argument, while the squaring should happen inside of the ``__init__`` method,
204
+ where it won't mess with the cache::
205
+
206
+ sage: class BetterUsage(CachedRepresentation):
207
+ ....: @staticmethod
208
+ ....: def __classcall__(cls, n):
209
+ ....: return super().__classcall__(cls, abs(n))
210
+ ....: def __init__(self, n):
211
+ ....: self.n = n^2
212
+ ....: def __repr__(self):
213
+ ....: return "SomethingElse(%d)"%self.n
214
+ sage: __main__.BetterUsage = BetterUsage # This is only needed in doctests
215
+ sage: b = BetterUsage(3); b
216
+ SomethingElse(9)
217
+ sage: loads(dumps(b)) is b
218
+ True
219
+ sage: b is BetterUsage(-3)
220
+ True
221
+
222
+ In our next example, we create a cached representation class ``C`` that
223
+ returns an instance of a sub-class ``C1`` or ``C2`` depending on the given
224
+ arguments. This is implemented in a static ``__classcall_private__`` method of
225
+ ``C``, letting it choose the sub-class according to the given arguments. Since
226
+ a ``__classcall_private__`` method will be ignored on sub-classes, the caching
227
+ of :class:`CachedRepresentation` is available to both ``C1`` and ``C2``. But
228
+ for illustration, we overload the static ``__classcall__`` method on ``C2``,
229
+ doing some argument preprocessing. We also create a sub-class ``C2b`` of
230
+ ``C2``, demonstrating that the ``__classcall__`` method is used on the
231
+ sub-class (in contrast to a ``__classcall_private__`` method!). ::
232
+
233
+ sage: class C(CachedRepresentation):
234
+ ....: @staticmethod
235
+ ....: def __classcall_private__(cls, n, implementation=0):
236
+ ....: if not implementation:
237
+ ....: return C.__classcall__(cls, n)
238
+ ....: if implementation==1:
239
+ ....: return C1(n)
240
+ ....: if implementation>1:
241
+ ....: return C2(n,implementation)
242
+ ....: def __init__(self, n):
243
+ ....: self.n = n
244
+ ....: def __repr__(self):
245
+ ....: return "C(%d, 0)"%self.n
246
+ sage: class C1(C):
247
+ ....: def __repr__(self):
248
+ ....: return "C1(%d)"%self.n
249
+ sage: class C2(C):
250
+ ....: @staticmethod
251
+ ....: def __classcall__(cls, n, implementation=0):
252
+ ....: if implementation:
253
+ ....: return super().__classcall__(cls, (n,)*implementation)
254
+ ....: return super().__classcall__(cls, n)
255
+ ....: def __init__(self, t):
256
+ ....: self.t = t
257
+ ....: def __repr__(self):
258
+ ....: return "C2(%s)"%repr(self.t)
259
+ sage: class C2b(C2):
260
+ ....: def __repr__(self):
261
+ ....: return "C2b(%s)"%repr(self.t)
262
+ sage: __main__.C2 = C2 # not needed in an interactive session
263
+ sage: __main__.C2b = C2b
264
+
265
+ In the above example, ``C`` drops the argument ``implementation`` if it
266
+ evaluates to ``False``, and since the cached ``__classcall__`` is called in
267
+ this case, we have::
268
+
269
+ sage: C(1)
270
+ C(1, 0)
271
+ sage: C(1) is C(1,0)
272
+ True
273
+ sage: C(1) is C(1,0) is C(1,None) is C(1,[])
274
+ True
275
+
276
+ (Note that we were able to bypass the issue of arguments having to be
277
+ hashable by catching the empty list ``[]`` during preprocessing in the
278
+ ``__classcall_private__`` method. Similarly, unhashable arguments can
279
+ be made hashable -- e. g., lists normalized to tuples -- in the
280
+ ``__classcall_private__`` method before they are further delegated to
281
+ ``__classcall__``. See
282
+ :class:`~sage.combinat.crystals.elementary_crystals.TCrystal` for an
283
+ example.)
284
+
285
+ If we call ``C1`` directly or if we provide ``implementation=1`` to ``C``, we
286
+ obtain an instance of ``C1``. Since it uses the ``__classcall__`` method
287
+ inherited from :class:`CachedRepresentation`, the resulting instances are
288
+ cached::
289
+
290
+ sage: C1(2)
291
+ C1(2)
292
+ sage: C(2, implementation=1)
293
+ C1(2)
294
+ sage: C(2, implementation=1) is C1(2)
295
+ True
296
+
297
+ The class ``C2`` preprocesses the input arguments. Instances can, again, be
298
+ obtained directly or by calling ``C``::
299
+
300
+ sage: C(1, implementation=3)
301
+ C2((1, 1, 1))
302
+ sage: C(1, implementation=3) is C2(1,3)
303
+ True
304
+
305
+ The argument preprocessing of ``C2`` is inherited by ``C2b``, since
306
+ ``__classcall__`` and not ``__classcall_private__`` is used. Pickling works,
307
+ since the preprocessing of arguments is idempotent::
308
+
309
+ sage: c2b = C2b(2,3); c2b
310
+ C2b((2, 2, 2))
311
+ sage: loads(dumps(c2b)) is c2b
312
+ True
313
+
314
+ Using :class:`~sage.structure.factory.UniqueFactory`
315
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
316
+
317
+ For creating a cached representation using a factory, one has to
318
+
319
+ - create a class *separately* from the factory. This class **must** inherit
320
+ from :class:`object`. Its instances **must** allow attribute assignment.
321
+ - write a method ``create_key`` (or ``create_key_and_extra_args``) that
322
+ creates the cache key from the given arguments.
323
+ - write a method ``create_object`` that creates an instance of the class
324
+ from a given cache key.
325
+ - create an instance of the factory with a name that allows to conclude where
326
+ it is defined.
327
+
328
+ An example::
329
+
330
+ sage: class C():
331
+ ....: def __init__(self, t):
332
+ ....: self.t = t
333
+ ....: def __repr__(self):
334
+ ....: return "C%s"%repr(self.t)
335
+ sage: from sage.structure.factory import UniqueFactory
336
+ sage: class MyFactory(UniqueFactory):
337
+ ....: def create_key(self, n, m=None):
338
+ ....: if isinstance(n, (tuple,list)) and m is None:
339
+ ....: return tuple(n)
340
+ ....: return (n,)*m
341
+ ....: def create_object(self, version, key, **extra_args):
342
+ ....: # We ignore version and extra_args
343
+ ....: return C(key)
344
+
345
+ Now, we define an instance of the factory, stating that it can be found under
346
+ the name ``'F'`` in the ``__main__`` module. By consequence, pickling works::
347
+
348
+ sage: F = MyFactory("__main__.F")
349
+ sage: __main__.F = F # not needed in an interactive session
350
+ sage: loads(dumps(F)) is F
351
+ True
352
+
353
+ We can now create *cached* instances of ``C`` by calling the factory. The
354
+ cache only takes into account the key computed with the method ``create_key``
355
+ that we provided. Hence, different given arguments may result in the same
356
+ instance. Note that, again, the cache is weak, hence, the instance might be
357
+ removed from the cache during garbage collection, unless an external reference
358
+ is preserved.
359
+ ::
360
+
361
+ sage: a = F(1, 2); a
362
+ C(1, 1)
363
+ sage: a is F((1,1))
364
+ True
365
+
366
+ **If** the class of the returned instances is a sub-class of :class:`object`,
367
+ and **if** the resulting instance allows attribute assignment, then pickling
368
+ of the resulting instances is automatically provided for, and respects the
369
+ cache. ::
370
+
371
+ sage: loads(dumps(a)) is a
372
+ True
373
+
374
+ This is because an attribute is stored that explains how the instance was
375
+ created::
376
+
377
+ sage: a._factory_data
378
+ (<__main__.MyFactory object at ...>, (...), (1, 1), {})
379
+
380
+ .. NOTE::
381
+
382
+ If a class is used that does not inherit from :class:`object` then unique
383
+ pickling is *not* provided.
384
+
385
+ Caching is only available if the factory is called. If an instance of the
386
+ class is directly created, then the cache is not used::
387
+
388
+ sage: C((1,1))
389
+ C(1, 1)
390
+ sage: C((1,1)) is a
391
+ False
392
+
393
+ Comparing the two ways of implementing a cached representation
394
+ --------------------------------------------------------------
395
+
396
+ In this sub-section, we discuss advantages and disadvantages of the two ways
397
+ of implementing a cached representation, depending on the type of application.
398
+
399
+ Simplicity and transparency
400
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^
401
+
402
+ In many cases, turning a class into a cached representation requires nothing
403
+ more than adding :class:`CachedRepresentation` to the list of base classes of
404
+ this class. This is, of course, a very easy and convenient way. Writing a
405
+ factory would involve a lot more work.
406
+
407
+ If preprocessing of the arguments is needed, then we have seen how to do this
408
+ by a ``__classcall_private__`` or ``__classcall__`` method. But these are
409
+ double underscore methods and hence, for example, invisible in the
410
+ automatically created reference manual. Moreover, preprocessing *and* caching
411
+ are implemented in the same method, which might be confusing. In a unique
412
+ factory, these two tasks are cleanly implemented in two separate methods.
413
+ With a factory, it is possible to create the resulting instance by arguments
414
+ that are different from the key used for caching. This is significantly
415
+ restricted with CachedRepresentation due to the requirement that argument
416
+ preprocessing be idempotent.
417
+
418
+ Hence, if advanced preprocessing is needed, then
419
+ :class:`~sage.structure.factory.UniqueFactory` might be easier and more
420
+ transparent to use than :class:`CachedRepresentation`.
421
+
422
+ Class inheritance
423
+ ^^^^^^^^^^^^^^^^^
424
+
425
+ Using :class:`CachedRepresentation` has the advantage that one has a class and
426
+ creates cached instances of this class by the usual Python syntax::
427
+
428
+ sage: G = SymmetricGroup(6) # needs sage.groups
429
+ sage: issubclass(SymmetricGroup, sage.structure.unique_representation.CachedRepresentation) # needs sage.groups
430
+ True
431
+ sage: isinstance(G, SymmetricGroup) # needs sage.groups
432
+ True
433
+
434
+ In contrast, a factory is just a callable object that returns something that
435
+ has absolutely nothing to do with the factory, and may in fact return
436
+ instances of quite different classes::
437
+
438
+ sage: isinstance(GF, sage.structure.factory.UniqueFactory)
439
+ True
440
+ sage: K5 = GF(5)
441
+ sage: type(K5)
442
+ <class 'sage.rings.finite_rings.finite_field_prime_modn.FiniteField_prime_modn_with_category'>
443
+
444
+ sage: # needs sage.rings.finite_rings
445
+ sage: K25 = GF(25, 'x')
446
+ sage: type(K25) # needs sage.libs.linbox
447
+ <class 'sage.rings.finite_rings.finite_field_givaro.FiniteField_givaro_with_category'>
448
+ sage: Kp = GF(next_prime_power(1000000)^2, 'x')
449
+ sage: type(Kp)
450
+ <class 'sage.rings.finite_rings.finite_field_pari_ffelt.FiniteField_pari_ffelt_with_category'>
451
+
452
+ This can be confusing to the user. Namely, the user might determine the class
453
+ of an instance and try to create further instances by calling the class rather
454
+ than the factory---which is a mistake since it works around the cache (and
455
+ also since the class might be more restrictive than the factory -- i. e., the
456
+ type of ``K5`` in the above doctest cannot be called on a prime power which
457
+ is not a prime). This mistake can more easily be avoided by using
458
+ :class:`CachedRepresentation`.
459
+
460
+ We have seen above that one can easily create new cached-representation
461
+ classes by subclassing an existing cached-representation class, even making
462
+ use of an existing argument preprocess. This would be much more complicated
463
+ with a factory. Namely, one would need to rewrite old factories making them
464
+ aware of the new classes, and/or write new factories for the new classes.
465
+
466
+ Python versus extension classes
467
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
468
+
469
+ :class:`CachedRepresentation` uses a metaclass, namely
470
+ :class:`~sage.misc.classcall_metaclass.ClasscallMetaclass`. Hence, it can
471
+ currently not be a Cython extension class. Moreover, it is supposed to be used
472
+ by providing it as a base class. But in typical applications, one also has
473
+ another base class, say, :class:`~sage.structure.parent.Parent`. Hence, one
474
+ would like to create a class with at least two base classes, which is
475
+ currently impossible in Cython extension classes.
476
+
477
+ In other words, when using :class:`CachedRepresentation`, one must work with
478
+ Python classes. These can be defined in Cython code (``.pyx`` files) and can
479
+ thus benefit from Cython's speed inside of their methods, but they must not be
480
+ ``cdef class`` and can thus not use ``cdef`` attributes or methods.
481
+
482
+ Such restrictions do not exist when using a factory. However, if attribute
483
+ assignment does not work, then the automatic pickling provided by
484
+ :class:`~sage.structure.factory.UniqueFactory` will not be available.
485
+
486
+ What is a unique representation?
487
+ ================================
488
+
489
+ Instances of a class have a *unique instance behavior* when instances of this
490
+ class evaluate equal if and only if they are identical. Sage provides the base
491
+ class :class:`~sage.misc.fast_methods.WithEqualityById`, which provides
492
+ comparison by identity and a hash that is determined by the memory address of
493
+ the instance. Both the equality test and the hash are implemented in Cython
494
+ and are very fast, even when one has a Python class inheriting from
495
+ :class:`~sage.misc.fast_methods.WithEqualityById`.
496
+
497
+ In many applications, one wants to combine unique instance and cached
498
+ representation behaviour. This is called *unique representation* behaviour.
499
+ We have seen above that symmetric groups have a *cached* representation
500
+ behaviour. However, they do not show the *unique* representation behaviour,
501
+ since they are equal to groups created in a totally different way, namely to
502
+ subgroups::
503
+
504
+ sage: # needs sage.groups
505
+ sage: G = SymmetricGroup(6)
506
+ sage: G3 = G.subgroup([G((1,2,3,4,5,6)), G((1,2))])
507
+ sage: G is G3
508
+ False
509
+ sage: type(G) == type(G3)
510
+ False
511
+ sage: G == G3
512
+ True
513
+
514
+ The unique representation behaviour can conveniently be implemented with a
515
+ class that inherits from :class:`UniqueRepresentation`: By adding
516
+ :class:`UniqueRepresentation` to the base classes, the class will
517
+ simultaneously inherit from :class:`CachedRepresentation` and from
518
+ :class:`~sage.misc.fast_methods.WithEqualityById`.
519
+
520
+ For example, a symmetric function algebra is uniquely determined by the base
521
+ ring. Thus, it is reasonable to use :class:`UniqueRepresentation` in this
522
+ case::
523
+
524
+ sage: isinstance(SymmetricFunctions(CC), SymmetricFunctions) # needs sage.combinat sage.modules sage.rings.real_mpfr
525
+ True
526
+ sage: issubclass(SymmetricFunctions, UniqueRepresentation) # needs sage.combinat sage.modules
527
+ True
528
+
529
+ :class:`UniqueRepresentation` differs from :class:`CachedRepresentation` only
530
+ by adding :class:`~sage.misc.fast_methods.WithEqualityById` as a base
531
+ class. Hence, the above examples of argument preprocessing work for
532
+ :class:`UniqueRepresentation` as well.
533
+
534
+ Note that a cached representation created with
535
+ :class:`~sage.structure.factory.UniqueFactory` does *not* automatically
536
+ provide unique representation behaviour, in spite of its name! Hence, for
537
+ unique representation behaviour, one has to implement hash and equality test
538
+ accordingly, for example by inheriting from
539
+ :class:`~sage.misc.fast_methods.WithEqualityById`.
540
+ """
541
+ # ****************************************************************************
542
+ # Copyright (C) 2008 Nicolas M. Thiery <nthiery at users.sf.net>
543
+ # Copyright (C) 2013 Simon A. King <simon.king at uni-jena.de>
544
+ #
545
+ # Distributed under the terms of the GNU General Public License (GPL)
546
+ #
547
+ # This code is distributed in the hope that it will be useful,
548
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
549
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
550
+ # General Public License for more details.
551
+ #
552
+ # The full text of the GPL is available at:
553
+ #
554
+ # https://www.gnu.org/licenses/
555
+ # *****************************************************************************
556
+
557
+ from sage.misc.cachefunc import weak_cached_function
558
+ from sage.misc.classcall_metaclass import ClasscallMetaclass, typecall
559
+ from sage.misc.fast_methods import WithEqualityById
560
+
561
+
562
+ class WithPicklingByInitArgs(metaclass=ClasscallMetaclass):
563
+ r"""
564
+ Classes derived from :class:`WithPicklingByInitArgs` store the arguments
565
+ passed to :meth:`__init__` to implement pickling.
566
+
567
+ This class is for objects that are semantically immutable and determined
568
+ by the class and the arguments passed to :meth:`__init__`.
569
+ The class also provides implementations of :meth:`__copy__` and
570
+ :func:`__deepcopy__`, which simply return the object.
571
+ """
572
+
573
+ @staticmethod
574
+ def __classcall__(cls, *args, **options):
575
+ """
576
+ Construct a new object of this class and store the arguments passed to ``__init__``.
577
+
578
+ TESTS::
579
+
580
+ sage: from sage.structure.unique_representation import WithPicklingByInitArgs
581
+ sage: class MyClass(WithPicklingByInitArgs):
582
+ ....: def __init__(self, value):
583
+ ....: self.value = value
584
+ ....: def __eq__(self, other):
585
+ ....: if type(self) != type(other):
586
+ ....: return False
587
+ ....: return self.value == other.value
588
+ sage: import __main__
589
+ sage: __main__.MyClass = MyClass # This is only needed in doctests
590
+ sage: x = MyClass(1)
591
+ sage: x == loads(dumps(x))
592
+ True
593
+ sage: y = MyClass(1)
594
+ sage: x is y # No Cached/UniqueRepresentation behavior
595
+ False
596
+ """
597
+ instance = typecall(cls, *args, **options)
598
+ assert isinstance(instance, cls)
599
+ if instance.__class__.__reduce__ == WithPicklingByInitArgs.__reduce__:
600
+ instance._reduction = (cls, args, options)
601
+ return instance
602
+
603
+ def __reduce__(self):
604
+ """
605
+ Return the arguments that have been passed to
606
+ :meth:`__new__<object.__new__>` to construct this object,
607
+ as per the pickle protocol.
608
+
609
+ See also :class:`CachedRepresentation` and
610
+ :class:`UniqueRepresentation` for a discussion.
611
+
612
+ EXAMPLES::
613
+
614
+ sage: x = UniqueRepresentation()
615
+ sage: x.__reduce__() # indirect doctest
616
+ (<function unreduce at ...>, (<class 'sage.structure.unique_representation.UniqueRepresentation'>, (), {}))
617
+ """
618
+ return (unreduce, self._reduction)
619
+
620
+ def __copy__(self):
621
+ """
622
+ Return ``self``, as a semantic copy of ``self``.
623
+
624
+ This assumes that the object is semantically immutable.
625
+
626
+ EXAMPLES::
627
+
628
+ sage: x = UniqueRepresentation()
629
+ sage: x is copy(x) # indirect doctest
630
+ True
631
+ """
632
+ return self
633
+
634
+ def __deepcopy__(self, memo):
635
+ """
636
+ Return ``self``, as a semantic deep copy of ``self``.
637
+
638
+ This assumes that the object is semantically immutable.
639
+
640
+ EXAMPLES::
641
+
642
+ sage: from copy import deepcopy
643
+ sage: x = UniqueRepresentation()
644
+ sage: x is deepcopy(x) # indirect doctest
645
+ True
646
+ """
647
+ return self
648
+
649
+
650
+ def unreduce(cls, args, keywords):
651
+ """
652
+ Calls a class on the given arguments::
653
+
654
+ sage: sage.structure.unique_representation.unreduce(Integer, (1,), {})
655
+ 1
656
+
657
+ .. TODO::
658
+
659
+ should reuse something preexisting ...
660
+
661
+ """
662
+ return cls(*args, **keywords)
663
+
664
+
665
+ class CachedRepresentation(WithPicklingByInitArgs):
666
+ """
667
+ Classes derived from CachedRepresentation inherit a weak cache for their
668
+ instances.
669
+
670
+ .. NOTE::
671
+
672
+ If this class is used as a base class, then instances are (weakly)
673
+ cached, according to the arguments used to create the instance.
674
+ Pickling is provided, of course by using the cache.
675
+
676
+ .. NOTE::
677
+
678
+ Using this class, one can have arbitrary hash and comparison.
679
+ Hence, *unique* representation behaviour is *not* provided.
680
+
681
+ .. SEEALSO::
682
+
683
+ :class:`UniqueRepresentation`, :mod:`~sage.structure.unique_representation`
684
+
685
+ EXAMPLES:
686
+
687
+ Providing a class with a weak cache for the instances is easy: Just
688
+ inherit from :class:`CachedRepresentation`::
689
+
690
+ sage: from sage.structure.unique_representation import CachedRepresentation
691
+ sage: class MyClass(CachedRepresentation):
692
+ ....: # all the rest as usual
693
+ ....: pass
694
+
695
+ We start with a simple class whose constructor takes a single
696
+ value as argument (TODO: find a more meaningful example)::
697
+
698
+ sage: class MyClass(CachedRepresentation):
699
+ ....: def __init__(self, value):
700
+ ....: self.value = value
701
+ ....: def __eq__(self, other):
702
+ ....: if type(self) != type(other):
703
+ ....: return False
704
+ ....: return self.value == other.value
705
+
706
+ Two coexisting instances of ``MyClass`` created with the same argument data
707
+ are guaranteed to share the same identity. Since :issue:`12215`, this is
708
+ only the case if there is some strong reference to the returned instance,
709
+ since otherwise it may be garbage collected::
710
+
711
+ sage: x = MyClass(1)
712
+ sage: y = MyClass(1)
713
+ sage: x is y # There is a strong reference
714
+ True
715
+ sage: z = MyClass(2)
716
+ sage: x is z
717
+ False
718
+
719
+ In particular, modifying any one of them modifies the other
720
+ (reference effect)::
721
+
722
+ sage: x.value = 3
723
+ sage: x.value, y.value
724
+ (3, 3)
725
+ sage: y.value = 1
726
+ sage: x.value, y.value
727
+ (1, 1)
728
+
729
+ The arguments can consist of any combination of positional or keyword
730
+ arguments, as taken by a usual :meth:`__init__ <object.__init__>`
731
+ function. However, all values passed in should be hashable::
732
+
733
+ sage: MyClass(value = [1,2,3])
734
+ Traceback (most recent call last):
735
+ ...
736
+ TypeError: ...unhashable type: 'list'...
737
+
738
+ .. rubric:: Argument preprocessing
739
+
740
+ Sometimes, one wants to do some preprocessing on the arguments, to
741
+ put them in some canonical form. The following example illustrates
742
+ how to achieve this; it takes as argument any iterable, and
743
+ canonicalizes it into a tuple (which is hashable!)::
744
+
745
+ sage: class MyClass2(CachedRepresentation):
746
+ ....: @staticmethod
747
+ ....: def __classcall__(cls, iterable):
748
+ ....: t = tuple(iterable)
749
+ ....: return super().__classcall__(cls, t)
750
+ ....:
751
+ ....: def __init__(self, value):
752
+ ....: self.value = value
753
+ sage: x = MyClass2([1,2,3])
754
+ sage: y = MyClass2(tuple([1,2,3]))
755
+ sage: z = MyClass2(i for i in [1,2,3])
756
+ sage: x.value
757
+ (1, 2, 3)
758
+ sage: x is y, y is z
759
+ (True, True)
760
+
761
+ A similar situation arises when the constructor accepts default
762
+ values for some of its parameters. Alas, the obvious
763
+ implementation does not work::
764
+
765
+ sage: class MyClass3(CachedRepresentation):
766
+ ....: def __init__(self, value=3):
767
+ ....: self.value = value
768
+ sage: MyClass3(3) is MyClass3()
769
+ False
770
+
771
+ Instead, one should do::
772
+
773
+ sage: class MyClass3(UniqueRepresentation):
774
+ ....: @staticmethod
775
+ ....: def __classcall__(cls, value=3):
776
+ ....: return super().__classcall__(cls, value)
777
+ ....:
778
+ ....: def __init__(self, value):
779
+ ....: self.value = value
780
+ sage: MyClass3(3) is MyClass3()
781
+ True
782
+
783
+ A bit of explanation is in order. First, the call ``MyClass2([1,2,3])``
784
+ triggers a call to ``MyClass2.__classcall__(MyClass2, [1,2,3])``. This is
785
+ an extension of the standard Python behavior, needed by
786
+ :class:`CachedRepresentation`, and implemented by the
787
+ :class:`~sage.misc.classcall_metaclass.ClasscallMetaclass`. Then,
788
+ ``MyClass2.__classcall__`` does the desired transformations on the
789
+ arguments. Finally, it uses ``super`` to call the default implementation
790
+ of ``__classcall__`` provided by :class:`CachedRepresentation`. This one
791
+ in turn handles the caching and, if needed, constructs and initializes a
792
+ new object in the class using :meth:`__new__<object.__new__>` and
793
+ :meth:`__init__<object.__init__>` as usual.
794
+
795
+ Constraints:
796
+
797
+ - :meth:`__classcall__` is a staticmethod (like, implicitly,
798
+ :meth:`__new__<object.__new__>`)
799
+ - the preprocessing on the arguments should be idempotent. That is, if
800
+ ``MyClass2.__classcall__(<arguments>)`` calls
801
+ ``CachedRepresentation.__classcall__(<preprocessed_arguments>)``, then
802
+ ``MyClass2.__classcall__(<preprocessed_arguments>)`` should also result
803
+ in a call to ``CachedRepresentation.__classcall__(<preprocessed_arguments>)``.
804
+ - ``MyClass2.__classcall__`` should return the result of
805
+ :meth:`CachedRepresentation.__classcall__` without modifying it.
806
+
807
+ Other than that ``MyClass2.__classcall__`` may play any tricks, like
808
+ acting as a factory and returning objects from other classes.
809
+
810
+ .. WARNING::
811
+
812
+ It is possible, but strongly discouraged, to let the ``__classcall__``
813
+ method of a class ``C`` return objects that are not instances of
814
+ ``C``. Of course, instances of a *subclass* of ``C`` are fine. Compare
815
+ the examples in :mod:`~sage.structure.unique_representation`.
816
+
817
+ We illustrate what is meant by an "idempotent" preprocessing. Imagine
818
+ that one has instances that are created with an integer-valued argument,
819
+ but only depend on the *square* of the argument. It would be a mistake to
820
+ square the given argument during preprocessing::
821
+
822
+ sage: class WrongUsage(CachedRepresentation):
823
+ ....: @staticmethod
824
+ ....: def __classcall__(cls, n):
825
+ ....: return super().__classcall__(cls, n^2)
826
+ ....: def __init__(self, n):
827
+ ....: self.n = n
828
+ ....: def __repr__(self):
829
+ ....: return "Something(%d)"%self.n
830
+ sage: import __main__
831
+ sage: __main__.WrongUsage = WrongUsage # This is only needed in doctests
832
+ sage: w = WrongUsage(3); w
833
+ Something(9)
834
+ sage: w._reduction
835
+ (<class '__main__.WrongUsage'>, (9,), {})
836
+
837
+ Indeed, the reduction data are obtained from the preprocessed
838
+ arguments. By consequence, if the resulting instance is pickled and
839
+ unpickled, the argument gets squared *again*::
840
+
841
+ sage: loads(dumps(w))
842
+ Something(81)
843
+
844
+ Instead, the preprocessing should only take the absolute value of the
845
+ given argument, while the squaring should happen inside of the
846
+ ``__init__`` method, where it won't mess with the cache::
847
+
848
+ sage: class BetterUsage(CachedRepresentation):
849
+ ....: @staticmethod
850
+ ....: def __classcall__(cls, n):
851
+ ....: return super().__classcall__(cls, abs(n))
852
+ ....: def __init__(self, n):
853
+ ....: self.n = n^2
854
+ ....: def __repr__(self):
855
+ ....: return "SomethingElse(%d)"%self.n
856
+ sage: __main__.BetterUsage = BetterUsage # This is only needed in doctests
857
+ sage: b = BetterUsage(3); b
858
+ SomethingElse(9)
859
+ sage: loads(dumps(b)) is b
860
+ True
861
+ sage: b is BetterUsage(-3)
862
+ True
863
+
864
+ .. rubric:: Cached representation and mutability
865
+
866
+ :class:`CachedRepresentation` is primarily intended for implementing
867
+ objects which are (at least semantically) immutable. This is in
868
+ particular assumed by the default implementations of ``copy`` and
869
+ ``deepcopy``::
870
+
871
+ sage: copy(x) is x
872
+ True
873
+ sage: from copy import deepcopy
874
+ sage: deepcopy(x) is x
875
+ True
876
+
877
+ However, in contrast to :class:`UniqueRepresentation`, using
878
+ :class:`CachedRepresentation` allows for a comparison that is not by
879
+ identity::
880
+
881
+ sage: t = MyClass(3)
882
+ sage: z = MyClass(2)
883
+ sage: t.value = 2
884
+
885
+ Now ``t`` and ``z`` are non-identical, but equal::
886
+
887
+ sage: t.value == z.value
888
+ True
889
+ sage: t == z
890
+ True
891
+ sage: t is z
892
+ False
893
+
894
+ .. rubric:: More on cached representation and identity
895
+
896
+ :class:`CachedRepresentation` is implemented by means of a cache.
897
+ This cache uses weak references in general, but strong references to
898
+ the most recently created objects. Hence, when all other references
899
+ to, say, ``MyClass(1)`` have been deleted, the instance is
900
+ eventually deleted from memory (after enough other objects have been
901
+ created to remove the strong reference to ``MyClass(1)``). A later
902
+ call to ``MyClass(1)`` reconstructs the instance from scratch::
903
+
904
+ sage: class SomeClass(UniqueRepresentation):
905
+ ....: def __init__(self, i):
906
+ ....: print("creating new instance for argument %s" % i)
907
+ ....: self.i = i
908
+ ....: def __del__(self):
909
+ ....: print("deleting instance for argument %s" % self.i)
910
+ sage: class OtherClass(UniqueRepresentation):
911
+ ....: def __init__(self, i):
912
+ ....: pass
913
+ sage: O = SomeClass(1)
914
+ creating new instance for argument 1
915
+ sage: O is SomeClass(1)
916
+ True
917
+ sage: O is SomeClass(2)
918
+ creating new instance for argument 2
919
+ False
920
+ sage: L = [OtherClass(i) for i in range(200)]
921
+ deleting instance for argument 2
922
+ sage: del O
923
+ deleting instance for argument 1
924
+ sage: O = SomeClass(1)
925
+ creating new instance for argument 1
926
+ sage: del O
927
+ sage: del L
928
+ sage: L = [OtherClass(i) for i in range(200)]
929
+ deleting instance for argument 1
930
+
931
+ .. rubric:: Cached representation and pickling
932
+
933
+ The default Python pickling implementation (by reconstructing an object
934
+ from its class and dictionary, see "The pickle protocol" in the Python
935
+ Library Reference) does not preserve cached representation, as Python has
936
+ no chance to know whether and where the same object already exists.
937
+
938
+ :class:`CachedRepresentation` tries to ensure appropriate pickling by
939
+ implementing a :meth:`__reduce__ <object.__reduce__>` method returning the
940
+ arguments passed to the constructor::
941
+
942
+ sage: import __main__ # Fake MyClass being defined in a python module
943
+ sage: __main__.MyClass = MyClass
944
+ sage: x = MyClass(1)
945
+ sage: loads(dumps(x)) is x
946
+ True
947
+
948
+ :class:`CachedRepresentation` uses the :meth:`__reduce__
949
+ <object.__reduce__>` pickle protocol rather than :meth:`__getnewargs__
950
+ <object.__getnewargs__>` because the latter does not handle keyword
951
+ arguments::
952
+
953
+ sage: x = MyClass(value = 1)
954
+ sage: x.__reduce__()
955
+ (<function unreduce at ...>, (<class '__main__.MyClass'>, (), {'value': 1}))
956
+ sage: x is loads(dumps(x))
957
+ True
958
+
959
+ .. NOTE::
960
+
961
+ The default implementation of :meth:`__reduce__ <object.__reduce__>`
962
+ in :class:`CachedRepresentation` requires to store the constructor's
963
+ arguments in the instance dictionary upon construction::
964
+
965
+ sage: x.__dict__
966
+ {'_reduction': (<class '__main__.MyClass'>, (), {'value': 1}), 'value': 1}
967
+
968
+ It is often easy in a derived subclass to reconstruct the constructor's
969
+ arguments from the instance data structure. When this is the case,
970
+ :meth:`__reduce__ <object.__reduce__>` should be overridden; automagically
971
+ the arguments won't be stored anymore::
972
+
973
+ sage: class MyClass3(UniqueRepresentation):
974
+ ....: def __init__(self, value):
975
+ ....: self.value = value
976
+ ....:
977
+ ....: def __reduce__(self):
978
+ ....: return (MyClass3, (self.value,))
979
+ sage: import __main__; __main__.MyClass3 = MyClass3 # Fake MyClass3 being defined in a python module
980
+ sage: x = MyClass3(1)
981
+ sage: loads(dumps(x)) is x
982
+ True
983
+ sage: x.__dict__
984
+ {'value': 1}
985
+
986
+ .. rubric:: Migrating classes to ``CachedRepresentation`` and unpickling
987
+
988
+ We check that, when migrating a class to :class:`CachedRepresentation`,
989
+ older pickles can still be reasonably unpickled. Let us create a
990
+ (new style) class, and pickle one of its instances::
991
+
992
+ sage: class MyClass4():
993
+ ....: def __init__(self, value):
994
+ ....: self.value = value
995
+ sage: import __main__; __main__.MyClass4 = MyClass4 # Fake MyClass4 being defined in a python module
996
+ sage: pickle = dumps(MyClass4(1))
997
+
998
+ It can be unpickled::
999
+
1000
+ sage: y = loads(pickle)
1001
+ sage: y.value
1002
+ 1
1003
+
1004
+ Now, we upgrade the class to derive from :class:`UniqueRepresentation`,
1005
+ which inherits from :class:`CachedRepresentation`::
1006
+
1007
+ sage: class MyClass4(UniqueRepresentation, object):
1008
+ ....: def __init__(self, value):
1009
+ ....: self.value = value
1010
+ sage: import __main__; __main__.MyClass4 = MyClass4 # Fake MyClass4 being defined in a python module
1011
+ sage: __main__.MyClass4 = MyClass4
1012
+
1013
+ The pickle can still be unpickled::
1014
+
1015
+ sage: y = loads(pickle)
1016
+ sage: y.value
1017
+ 1
1018
+
1019
+ Note however that, for the reasons explained above, unique
1020
+ representation is not guaranteed in this case::
1021
+
1022
+ sage: y is MyClass4(1)
1023
+ False
1024
+
1025
+ .. TODO::
1026
+
1027
+ Illustrate how this can be fixed on a case by case basis.
1028
+
1029
+ Now, we redo the same test for a class deriving from SageObject::
1030
+
1031
+ sage: class MyClass4(SageObject):
1032
+ ....: def __init__(self, value):
1033
+ ....: self.value = value
1034
+ sage: import __main__; __main__.MyClass4 = MyClass4 # Fake MyClass4 being defined in a python module
1035
+ sage: pickle = dumps(MyClass4(1))
1036
+
1037
+ sage: class MyClass4(UniqueRepresentation, SageObject):
1038
+ ....: def __init__(self, value):
1039
+ ....: self.value = value
1040
+ sage: __main__.MyClass4 = MyClass4
1041
+ sage: y = loads(pickle)
1042
+ sage: y.value
1043
+ 1
1044
+
1045
+ Caveat: unpickling instances of a formerly old-style class is not supported yet by default::
1046
+
1047
+ sage: class MyClass4:
1048
+ ....: def __init__(self, value):
1049
+ ....: self.value = value
1050
+ sage: import __main__; __main__.MyClass4 = MyClass4 # Fake MyClass4 being defined in a python module
1051
+ sage: pickle = dumps(MyClass4(1))
1052
+
1053
+ sage: class MyClass4(UniqueRepresentation, SageObject):
1054
+ ....: def __init__(self, value):
1055
+ ....: self.value = value
1056
+ sage: __main__.MyClass4 = MyClass4
1057
+ sage: y = loads(pickle) # todo: not implemented
1058
+ sage: y.value # todo: not implemented
1059
+ 1
1060
+
1061
+ .. rubric:: Rationale for the current implementation
1062
+
1063
+ :class:`CachedRepresentation` and derived classes use the
1064
+ :class:`~sage.misc.classcall_metaclass.ClasscallMetaclass`
1065
+ of the standard Python type. The following example explains why.
1066
+
1067
+ We define a variant of ``MyClass`` where the calls to
1068
+ :meth:`__init__<object.__init__>` are traced::
1069
+
1070
+ sage: class MyClass(CachedRepresentation):
1071
+ ....: def __init__(self, value):
1072
+ ....: print("initializing object")
1073
+ ....: self.value = value
1074
+
1075
+ Let us create an object twice::
1076
+
1077
+ sage: x = MyClass(1)
1078
+ initializing object
1079
+ sage: z = MyClass(1)
1080
+
1081
+ As desired the :meth:`__init__<object.__init__>` method was only called
1082
+ the first time, which is an important feature.
1083
+
1084
+ As far as we can tell, this is not achievable while just using
1085
+ :meth:`__new__<object.__new__>` and :meth:`__init__<object.__init__>` (as
1086
+ defined by type; see Section :python:`Basic Customization
1087
+ <reference/datamodel.html#basic-customization>` in the Python Reference
1088
+ Manual). Indeed, :meth:`__init__<object.__init__>` is called
1089
+ systematically on the result of :meth:`__new__<object.__new__>` whenever
1090
+ the result is an instance of the class.
1091
+
1092
+ Another difficulty is that argument preprocessing (as in the example
1093
+ above) cannot be handled by :meth:`__new__<object.__new__>`, since the
1094
+ unprocessed arguments will be passed down to
1095
+ :meth:`__init__<object.__init__>`.
1096
+ """
1097
+
1098
+ @weak_cached_function(cache=128) # automatically a staticmethod
1099
+ def __classcall__(cls, *args, **options):
1100
+ """
1101
+ Construct a new object of this class or reuse an existing one.
1102
+
1103
+ See also :class:`CachedRepresentation` and
1104
+ :class:`UniqueRepresentation` for a discussion.
1105
+
1106
+ EXAMPLES::
1107
+
1108
+ sage: x = UniqueRepresentation()
1109
+ sage: y = UniqueRepresentation()
1110
+ sage: x is y # indirect doctest
1111
+ True
1112
+ """
1113
+ return super().__classcall__(cls, *args, **options)
1114
+
1115
+ @classmethod
1116
+ def _clear_cache_(cls):
1117
+ """
1118
+ Remove all instances of this class from the cache.
1119
+
1120
+ EXAMPLES:
1121
+
1122
+ If ``cls`` overloads :meth:`~sage.structure.unique_representation.CachedRepresentation.__classcall__`,
1123
+ clearing the cache still works, because ``cls.mro()``
1124
+ is searched until a ``__classcall__`` with an attribute
1125
+ ``cache`` is found::
1126
+
1127
+ sage: class A(UniqueRepresentation):
1128
+ ....: def __init__(self, x):
1129
+ ....: pass
1130
+ sage: class B(A):
1131
+ ....: @staticmethod
1132
+ ....: def __classcall__(cls, *args, **kwds):
1133
+ ....: return super().__classcall__(cls, *args, **kwds)
1134
+ sage: class C(B): pass
1135
+ sage: a = A(1)
1136
+ sage: b = B(2)
1137
+ sage: c = C(3)
1138
+ sage: a is A(1)
1139
+ True
1140
+ sage: b is B(2)
1141
+ True
1142
+ sage: c is C(3)
1143
+ True
1144
+ sage: B._clear_cache_()
1145
+
1146
+ Now, all instances of (sub-classes of) ``B`` have disappeared
1147
+ from the cache::
1148
+
1149
+ sage: a is A(1)
1150
+ True
1151
+ sage: b is B(2)
1152
+ False
1153
+ sage: c is C(3)
1154
+ False
1155
+
1156
+ Here is a similar example, using a private classcall in the class
1157
+ ``B``, which is not inherited by ``C``::
1158
+
1159
+ sage: class A(UniqueRepresentation):
1160
+ ....: def __init__(self, x):
1161
+ ....: pass
1162
+ sage: class B(A):
1163
+ ....: @staticmethod
1164
+ ....: def __classcall_private__(cls, *args, **kwds):
1165
+ ....: print("Private B")
1166
+ ....: return super().__classcall__(cls, *args, **kwds)
1167
+ sage: class C(B): pass
1168
+ sage: a = A(1)
1169
+ sage: b = B(2)
1170
+ Private B
1171
+ sage: c = C(3)
1172
+ sage: a is A(1)
1173
+ True
1174
+ sage: b is B(2)
1175
+ Private B
1176
+ True
1177
+ sage: c is C(3)
1178
+ True
1179
+ sage: B._clear_cache_()
1180
+
1181
+ Again, all instances of (sub-classes of) ``B`` have disappeared
1182
+ from the cache::
1183
+
1184
+ sage: a is A(1)
1185
+ True
1186
+ sage: b is B(2)
1187
+ Private B
1188
+ False
1189
+ sage: c is C(3)
1190
+ False
1191
+ """
1192
+ cache = None
1193
+ # not clear why the loop below is taking the last C
1194
+ for C in cls.mro():
1195
+ try:
1196
+ cache = C.__classcall__.cache
1197
+ except AttributeError:
1198
+ pass
1199
+ del_list = [k for k in cache if issubclass(k[0][0], cls)]
1200
+ for k in del_list:
1201
+ del cache[k]
1202
+
1203
+
1204
+ class UniqueRepresentation(WithEqualityById, CachedRepresentation):
1205
+ r"""
1206
+ Classes derived from ``UniqueRepresentation`` inherit a unique
1207
+ representation behavior for their instances.
1208
+
1209
+ .. SEEALSO::
1210
+
1211
+ :mod:`~sage.structure.unique_representation`
1212
+
1213
+ EXAMPLES:
1214
+
1215
+ The short story: to construct a class whose instances have a
1216
+ unique representation behavior one just has to do::
1217
+
1218
+ sage: class MyClass(UniqueRepresentation):
1219
+ ....: # all the rest as usual
1220
+ ....: pass
1221
+
1222
+ Everything below is for the curious or for advanced usage.
1223
+
1224
+ .. rubric:: What is unique representation?
1225
+
1226
+ Instances of a class have a *unique representation behavior* when
1227
+ instances evaluate equal if and only if they are identical (i.e., share
1228
+ the same memory representation), if and only if they were created using
1229
+ equal arguments. For example, calling twice::
1230
+
1231
+ sage: f = SymmetricFunctions(QQ) # needs sage.combinat sage.modules
1232
+ sage: g = SymmetricFunctions(QQ) # needs sage.combinat sage.modules
1233
+
1234
+ to create the symmetric function algebra over `\QQ` actually gives back the
1235
+ same object::
1236
+
1237
+ sage: f == g # needs sage.combinat sage.modules
1238
+ True
1239
+ sage: f is g # needs sage.combinat sage.modules
1240
+ True
1241
+
1242
+ This is a standard design pattern. It allows for sharing cached data (say
1243
+ representation theoretical information about a group) as well as for very
1244
+ fast hashing and equality testing. This behaviour is typically desirable
1245
+ for parents and categories. It can also be useful for intensive
1246
+ computations where one wants to cache all the operations on a small set of
1247
+ elements (say the multiplication table of a small group), and access this
1248
+ cache as quickly as possible.
1249
+
1250
+ :class:`UniqueRepresentation` is very easy to use: a class just needs to
1251
+ derive from it, or make sure some of its super classes does. Also, it
1252
+ groups together the class and the factory in a single gadget::
1253
+
1254
+ sage: isinstance(SymmetricFunctions(CC), SymmetricFunctions) # needs sage.combinat sage.modules
1255
+ True
1256
+ sage: issubclass(SymmetricFunctions, UniqueRepresentation) # needs sage.combinat sage.modules
1257
+ True
1258
+
1259
+ This nice behaviour is not available when one just uses a factory::
1260
+
1261
+ sage: isinstance(GF(7), GF)
1262
+ Traceback (most recent call last):
1263
+ ...
1264
+ TypeError: isinstance() arg 2 must be a type...
1265
+
1266
+ sage: isinstance(GF, sage.structure.factory.UniqueFactory)
1267
+ True
1268
+
1269
+ In addition, :class:`~sage.structure.factory.UniqueFactory` only provides
1270
+ the *cached* representation behaviour, but not the *unique* representation
1271
+ behaviour---the examples in :mod:`~sage.structure.unique_representation`
1272
+ explain this difference.
1273
+
1274
+ On the other hand, the :class:`UniqueRepresentation` class is more
1275
+ intrusive, as it imposes a behavior (and a metaclass) on all the
1276
+ subclasses. In particular, the unique representation behaviour is imposed
1277
+ on *all* subclasses (unless the ``__classcall__`` method is overloaded and
1278
+ not called in the subclass, which is not recommended). Its implementation
1279
+ is also more technical, which leads to some subtleties.
1280
+
1281
+ EXAMPLES:
1282
+
1283
+ We start with a simple class whose constructor takes a single value as
1284
+ argument. This pattern is similar to what is done in
1285
+ :class:`sage.combinat.sf.sf.SymmetricFunctions`::
1286
+
1287
+ sage: class MyClass(UniqueRepresentation):
1288
+ ....: def __init__(self, value):
1289
+ ....: self.value = value
1290
+
1291
+ Two coexisting instances of ``MyClass`` created with the same argument
1292
+ data are guaranteed to share the same identity. Since :issue:`12215`, this
1293
+ is only the case if there is some strong reference to the returned
1294
+ instance, since otherwise it may be garbage collected::
1295
+
1296
+ sage: x = MyClass(1)
1297
+ sage: y = MyClass(1)
1298
+ sage: x is y # There is a strong reference
1299
+ True
1300
+ sage: z = MyClass(2)
1301
+ sage: x is z
1302
+ False
1303
+
1304
+ In particular, modifying any one of them modifies the other
1305
+ (reference effect)::
1306
+
1307
+ sage: x.value = 3
1308
+ sage: x.value, y.value
1309
+ (3, 3)
1310
+ sage: y.value = 1
1311
+ sage: x.value, y.value
1312
+ (1, 1)
1313
+
1314
+ When comparing two instances of a unique representation with ``==``
1315
+ or ``!=`` comparison by identity is used::
1316
+
1317
+ sage: x == y
1318
+ True
1319
+ sage: x is y
1320
+ True
1321
+ sage: z = MyClass(2)
1322
+ sage: x == z
1323
+ False
1324
+ sage: x is z
1325
+ False
1326
+ sage: x != y
1327
+ False
1328
+ sage: x != z
1329
+ True
1330
+
1331
+ A hash function equivalent to :meth:`object.__hash__` is used, which is
1332
+ compatible with comparison by identity. However this means that the hash
1333
+ function may change in between Sage sessions, or even within the same Sage
1334
+ session.
1335
+ ::
1336
+
1337
+ sage: hash(x) == object.__hash__(x)
1338
+ True
1339
+
1340
+ .. WARNING::
1341
+
1342
+ It is possible to inherit from
1343
+ :class:`~sage.structure.unique_representation.UniqueRepresentation`
1344
+ and then overload comparison in a way that destroys the unique
1345
+ representation property. We strongly recommend against it! You should
1346
+ use :class:`~sage.structure.unique_representation.CachedRepresentation`
1347
+ instead.
1348
+
1349
+ .. rubric:: Mixing super types and super classes
1350
+
1351
+ TESTS:
1352
+
1353
+ For the record, this test did fail with previous implementation
1354
+ attempts::
1355
+
1356
+ sage: class bla(UniqueRepresentation, SageObject):
1357
+ ....: pass
1358
+ sage: b = bla()
1359
+ """