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 expression x - y, y instance of class has __rsub__() method, y.__rsub__(x) called if x.__sub__(y) returns notimplemented.

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

Popular posts from this blog

c# - Send Image in Json : 400 Bad request -

javascript - addthis share facebook and google+ url -

ios - Show keyboard with UITextField in the input accessory view -