IMHO the majority of Sage doesn't actually use dynamic category refinement and/or make the category depend on the arguments. And the latter is just a special case of the former.
If you really need to dynamically change the category then let the metaclass construct a suitable class and assign to __class__ or use a getattr hack. You still don't need differently-named classes Foo and Foo_with_category. On Friday, August 8, 2014 4:44:23 PM UTC+1, Simon King wrote: > > Hi Volker, > > some remark: > > On 2014-08-08, Volker Braun <vbrau...@gmail.com <javascript:>> wrote: > > IMHO the category > > functionality would have been better implemented by a proper metaclass > than > > by dynamically assigning to __class__ to dynamically construct the class > at > > import time, not at construction time. > > This would mean: You provide the category functionality during the > construction of the *class*, rather than during the construction time of > the *instance* of the class. > > Let Foo be a class whose instances may be objects in different categories > (such as matrix spaces, which are algebras if the matrices are square, and > modules otherwise). A metaclass can easily add methods of, say, > Modules(Rings()).parent_class to Foo (until recently, you would have > needed > to explicitly provide a base ring, rather than just saying that it belongs > to Rings()). > > But what would you do if Foo(args) has more structure and in fact belongs > to > Algebras(Rings())? I don't think that this can be solved on the level of > the class Foo, unless of course you provide Foo with a classcall > metaclass that, depending an the given arguments, dynamically creates a > new > class Foo_algebras adding the methods from Algebras(Rings()).parent_class, > and > then Foo(args) returns an instance of this new class Foo_algebras. > > But then, how would this be any better than what the category framework is > currently doing? > > Hmm. Perhaps actually it *is* better. Currently, the following happens: > > 1) Foo.__init__ choses a category CAT depending on the given arguments. > 2) _init_category_ replaces self.__class__ by a sub-class Foo_cat, that is > dynamically created using Foo and CAT. If Foo is a cython class, then > overriding self.__class__ by Foo_cat is impossible. > > With a (classcall) metaclass, we could make the following work: > > 1) When Foo(args) is called, we defer to Foo.__classcall__. > 2) In Foo.__classcall__, the category CAT is chosen depending on the > given args. Perhaps this could be done in some static method > Foo._choose_category_. > 3) Depending on CAT, a sub-class Foo_cat of Foo will be created and an > instance > O of it will be created and initialised. > 4) __classcall__ returns O. > > Advantages of the second scenario: > - Chosing the category is done in a separate method. Looks cleaner than > doing it in __init__. > - There will be no change of O.__class__ after creation of O, since O is > created as an instance of Foo_cat right away. > - This would work even if Foo was a Cython class. > > However, it would be an awful lot of work to change... > > Best regards, > Simon > > > -- 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 post to this group, send email to sage-devel@googlegroups.com. Visit this group at http://groups.google.com/group/sage-devel. For more options, visit https://groups.google.com/d/optout.