python - How to determine which instance of an operator is being called? -
i have class called mydata
has __mul__
, __rmul__
defined (along other arithmetic operators). whenever these methods used, should return value of type mydata
. however, discovered a * mydataobj
not same mydataobj * a
, depending on type of a
. specifically, if a
int
, worked fine, if a
float
first configuration return array (my object has numpy array member, , mydata.__getitem__
returns slices of array) , second configuration returns proper value of type mydata
.
is there way determine calling order of operator in expression this?
is there way determine calling order of operator in expression this?
first, exact rules described in data model section of language reference, "emulating numeric types" subsection.
the __rfoo__
methods described follows:
these methods called implement binary arithmetic operations (
+
,-
,*
,/
,%
,divmod()
,pow()
,**
,<<
,>>
,&
,^
,|
) reflected (swapped) operands. these functions called if left operand not support corresponding operation , operands of different types. [2] instance, evaluate expressionx - y
,y
instance of class has__rsub__()
method,y.__rsub__(x)
called ifx.__sub__(y)
returnsnotimplemented
.note ternary
pow()
not try calling__rpow__()
(the coercion rules become complicated).note if right operand’s type subclass of left operand’s type , subclass provides reflected method operation, method called before left operand’s non-reflected method. behavior allows subclasses override ancestors’ operations.
putting pythonesque pseudocode, x * y
evaluated this:
if type(y) type(x): return x.__mul__(y) elif type(y) subclass of type(x): try y.__rmul__(x) otherwise x.__mul__(y) else: try x.__mul__(y) otherwise y.__rmul__(x)
of course can determine calling order dynamically creating separate types methods print names , testing them:
class base(object): def __mul__(self, lhs): print('base.mul') def __rmul__(self, rhs): print('base.rmul') class derived(base): def __mul__(self, lhs): print('derived.mul') def __rmul__(self, rhs): print('derived.rmul') class unrelated(object): def __mul__(self, lhs): print('unrelated.mul') def __rmul__(self, rhs): print('unrelated.rmul') print('base * base: ', end='') base() * base() x, y in itertools.permutations((base, derived, unrelated), 2): print('{} * {}: '.format(x.__name__, y.__name__), end='') x() * y()
what built in types well?
exactly same rules. since base
not subclass of either int
or float
, , neither int
nor float
knows how multiply it, they'll both call base.__rmul__
. , other unrelated type throw @ it:
>>> base() * 2 base.mul >>> 2 * base() base.rmul >>> base() * 2.5 base.mul >>> 2.5 * base() base.rmul >>> 'sdfsdfsdfds' * base() base.rmul >>> (lambda: 23) * base() base.rmul
my problem i'm getting different results 1.5 * myobj , myobj * 1.5
there number of reasons that:
- your
__mul__
,__rmul__
code don't same thing. - you inherited
float
. - you inherited builtin or extension type handles float multiplication @ c-api level , isn't designed allow overrides in subclasses.
- you created classic class instead of new-style class.
- you made typo in 1 of names.
- …
Comments
Post a Comment