The problem is that H.as_algebra(Calculus) converts H to Calculus
instance while it should not, it should return NotImplemented.
I guess the default as_algebra is too nice - it tries hard to convert
any symbolic object to the algebra asked. It should be changed.
For your case, there is an easy fix:
def as_algebra(self, cls, typeerror=True):
return NotImplemented
With this, both problems are resolved:
>>> H*x-x*H
Operator('0')
Yes, all sympycore instances are derived from Expr that constructor
takes either one or two arguments. When two arguments ate given,
then they must be head and data parts of an instance ---- this is used
internally. When one argument is given, then it will be converted via
the convert method to Expr instance. So, to define a custom constructor,
you have two options:
1) collect all custom arguments to a tuple and redefine convert classmethod for
interpreting this tuple.
2) define __new__ method with your choice of constructor arguments
and explicitly create Expr instance.
I guess the last option would be more general, so, here is a (meaningless) example:
>>> class MyRing(Ring):
def __new__(cls, arg1, arg2 = 'a', arg3 = 'b'):
s = '%s_%s_%s' % (arg1, arg2, arg3)
obj = Expr.__new__(cls, heads.SYMBOL, s)
return obj
...
...
>>> MyRing('A')
MyRing('A_a_b')
>>> MyRing('A', 'c')
MyRing('A_c_b')
HTH,
Pearu