I thank all of you for your answers. And sorry for taking a bit long to reply!

After many trys and errors, here is something that works for me:

```

from sage.structure.sage_object import SageObject
from sage.structure.unique_representation import CachedRepresentation

class MyInteger(CachedRepresentation, SageObject):

    @staticmethod
    def __classcall_private__(cls, n):
        if n % 2 == 0:
            return MyInteger_even(n)
        else:
            return cls.__classcall__(cls, n)

    def __init__(self, n):
        self.n = n


class MyInteger_even(MyInteger):

    def __init__(self, n):
        self.n = n
        self.half = n // 2
```

However, this has a major drawback, as all instances that have same data are
references to one another. And I don't find any way to bypass that:

```

sage: from copy import deepcopy
sage: s1 = MyInteger(2)
sage: s2 = MyInteger(2)
sage: s3 = deepcopy(s2)
sage: s1 == s2
True
sage: s1 is s2
True
sage: s1 == s3
True
sage: s1 is s3
True
sage: s1.n
2
sage: s3.n = 5
sage: s1.n
5
sage: 
```

I appreciate that this may not be a problem for classes representing sets and
categories (like `EuclideanSpace`). But for classes representing children
elements, this may cause problems. And this is the case for me, as I need this
for `FiniteDrinfeldModule` and `FiniteDrinfeldModule_rank_two`
(https://trac.sagemath.org/ticket/33713).

Is there a way to avoid this?

Kindest regards,
Antoine

On Sat, 2022-05-14 at 21:07 -0700, Nils Bruin wrote:
> It's probably worth pointing out that __classcall_private__ is not a standard
> python facility. It looks like you need
> 
> class Foo(metaclass=ClasscallMetaclass):
> 
> to make it work on Foo.
> 
> On Saturday, 14 May 2022 at 20:21:48 UTC-7 Travis Scrimshaw wrote:
> > For this you want to use __classcall_private__ as otherwise you would likely
> > end up in an infinite loop when you try to construct the subclass. There are
> > lots of examples of this in the Sage library code.
> > 
> > Best,
> > Travis
> > 
> > 
> > On Sunday, May 15, 2022 at 5:42:49 AM UTC+9 Eric Gourgoulhon wrote:
> > > Hi, 
> > > 
> > > Le samedi 14 mai 2022 à 00:07:02 UTC+2, David Roe a écrit :
> > > > I think the following should work:
> > > > 
> > > > class MyObject:
> > > >     def __classcall__(cls, arg):
> > > >          if isinstance(arg, special):
> > > >              return typecall(MyObject_specific_case, arg)
> > > >          else:
> > > >              return typecall(MyObject, arg)
> > > > 
> > > > plus the same __init__ you had before.  I haven't checked it though....
> > > > David
> > > >               
> > > > 
> > > 
> > > 
> > > An alternative is to use __classcall_private__
> > > For an example, see the class EuclideanSpace in
> > > src/sage/manifolds/differentiable/examples/euclidean.py
> > > 
> > > EuclideanSpace(n) actually returns an instance of the subclass
> > > EuclideanPlane if n = 2 or of the subclass Euclidean3dimSpace if n = 3.
> > > 
> > > Best wishes,
> > > 
> > > Eric.
> -- 
> You received this message because you are subscribed to a topic in the Google
> Groups "sage-devel" group.
> To unsubscribe from this topic, visit
> https://groups.google.com/d/topic/sage-devel/PaUReuoxEXI/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to
> sage-devel+unsubscr...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/sage-devel/a8bc696f-7887-41b2-8fe9-af3ac055eb71n%40googlegroups.com
> .


-- 
You received this message because you are subscribed to the Google Groups 
"sage-devel" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sage-devel+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/sage-devel/e17a059b1fb7b120b08b088ca17d6a3df5b72d5f.camel%40gmail.com.

Reply via email to