Why I can't redefine the __and__ operator?
class Cut(object):
def __init__(self, cut):
self.cut = cut
def __and__(self, other):
return Cut("(" + self.cut + ") && (" + other.cut + ")")
a = Cut("a>0")
b = Cut("b>0")
c = a and b
print c.cut()
I want (a>0) && (b>0), but I got b, that the usual behaviour of and
__and__ is the binary (bitwise) & operator, not the logical and operator.
Because the and operator is a short-circuit operator, it can't be implemented as a function. That is, if the first argument is false, the second argument isn't evaluated at all. If you try to implement that as a function, both arguments have to be evaluated before the function can be invoked.
because you cannot redefine a keyword (that's what and is) in Python. __add__ is used to do something else:
These methods are called to implement the binary arithmetic operations (...&...
Related
Is it possible to define my own mathematical operator?
Like the introduction of the new # in PEP-465 for matrix multiplication or // for integer division.
Something like
a ! b -> a / (a + b)
You can use one of the predefined operator that has not been implemented for integers.
For example this one : # (matmul)
You cannot use ! character as it is not in this list.
class MyInt(int):
def __matmul__(self, other):
return self / (self + other)
Then you can do :
a = MyInt(1)
b = MyInt(2)
print(a # b)
Will print (0.33333333)
I am trying to understand how operator overriding works for two operands of a custom class.
For instance, suppose I have the following:
class Adder:
def __init__(self, value=1):
self.data = value
def __add__(self,other):
print('using __add__()')
return self.data + other
def __radd__(self,other):
print('using __radd__()')
return other + self.data
I initialize the following variables:
x = Adder(5)
y = Adder(4)
And then proceed to do the following operations:
1 + x
using __radd__()
Out[108]: 6
x + 2
using __add__()
Out[109]: 7
The two operations above seem straigtforward. If a member of my custom class is to the right of the "+" in the addition expression, then __radd__ is used. If it is on the left, then __add__ is used. This works for expressions when one operand is of the Adder type and another one is something else.
When I do this, however, I get the following result:
x + y
using __add__()
using __radd__()
Out[110]: 9
As you can see, if both operands are of the custom class, then both __add__ and __radd__ are called.
My question is how does Python unravel this situation and how is it able to call both the right-hand-addition function, as well as the left-hand-addition function.
It's because inside your methods you add the data to other. This is itself an instance of Adder. So the logic goes:
call __add__ on x;
add x.data (an int) to y (an Adder instance)
ah, right-hand operand is an instance with a __radd__ method, so
call __radd__ on y;
add int to y.data (another int).
Usually you would check to see if other was an instance of your class, and if so add other.data rather than just other.
That's the because the implementation of your __add__ and __radd__ method do not give any special treatment to the instances of the Adder class. Therefore, each __add__ call leads to an integer plus Adder instance operation which further requires __radd__ due to the Adder instance on the right side.
You can resolve this by doing:
def __add__(self, other):
print('using __add__()')
if isinstance(other, Adder):
other = other.data
return self.data + other
def __radd__(self, other):
print('using __radd__()')
return self.__add__(other)
I'd like to know how I would go about doing something like this (in python 2):
def myFunction(fn, params):
return ("You called " + fn.__name__ + "(" + str(params) ")" +
" and got " + str(fn(params)))
Say I have a couple functions:
def doSomething(s):
# manipulation
return s
def doAnotherThing(someInt, someOtherInt, someString):
# do something with them
return someValue
I'd like to be able to call myFunction(doSomething, "hello"), and get You called doSomething("hello") and got "something". This approach seems to work for functions that take a single input, but I can't get it to work for functions that take multiple inputs, e.g. calling myFunction(doAnotherThing, (myInt, myOtherInt, myString)). I think I need to do something involving * and ** so that I can take the keywords arbitrarily instead of as a tuple, but I'm not quite sure how to go about doing that.
You're close, all you need to do is add a * in front of the tuple (or ** in front of a dict for keyword arguments) when calling the interior function. This is called argument unpacking.
def wrapper(fn, params, keyword_params):
return fn(*params, **keyword_params)
def myfunc(a, b, c=0):
return (a + b)/c
wrapper(myfunc, (2, 5), {'c': 3})
You can also use arbitrary argument lists to potentially simplify the wrapper function. This will allow you to automatically package additional arguments to feed to interior functions without having to pre-package them in tuples and dictionaries.
def wrapper(fn, *params, **keyword_params): # Note the asterisks
return fn(*params, **keyword_params)
def myfunc(a, b, c=1):
return (a + b)/c
wrapper(myfunc, 2, 5, c=3) # Nicer function call
Note that just using the first method will actually break single-argument implementations, as the * operator expects an iterator to unpack. So you have to either always pre-package the arguments or add some type-checking in the wrapper function.
def wrapper(fn, params):
return fn(*params)
def myfunc(a):
return 2*a
wrapper(myfunc, 2)
# TypeError: myfunc() argument after * must be a sequence, not int
wrapper(myfunc, (2,)) # Package the argument in a single-element tuple
# 4
The second method doesn't have this problem.
Here is one way:
def myFunction(fn, *params):
return ("You called " + fn.__name__ + str(params) +
" and got " + str(fn(*params)))
import math
print myFunction(math.sqrt, 4)
print myFunction(open, '/etc/passwd', 'r')
print myFunction(lambda x: x+1, 41)
Result:
You called sqrt(4,) and got 2.0
You called open('/etc/passwd', 'r') and got <open file '/etc/passwd', mode 'r' at 0x7f20e9cb65d0>
You called <lambda>(41,) and got 42
I have a class called MyData that has __mul__ and __rmul__ defined (along with all the other arithmetic operators). Whenever these methods are used, it should always return a value of type MyData. However, I discovered that a * myDataObj is not the same as myDataObj * a, depending on the type of a. Specifically, if a was an int, it worked fine, but if a was a float then the first configuration return an array (my object has a numpy array as a member, and MyData.__getitem__ returns slices of that array) and the second configuration returns the proper value of type MyData.
Is there any way to determine the calling order of the operator in an expression like this?
Is there any way to determine the calling order of the operator in an expression like this?
First, the exact rules are described in the Data model section of the language reference, specifically the "Emulating numeric types" subsection.
The __rfoo__ methods are described as follows:
These methods are called to implement the binary arithmetic operations (+, -, *, /, %, divmod(), pow(), **, <<, >>, &, ^, |) with reflected (swapped) operands. These functions are only called if the left operand does not support the corresponding operation and the operands are of different types. [2] For instance, to evaluate the expression x - y, where y is an instance of a class that has an __rsub__() method, y.__rsub__(x) is called if x.__sub__(y) returns NotImplemented.
Note that ternary pow() will not try calling __rpow__() (the coercion rules would become too complicated).
Note If the right operand’s type is a subclass of the left operand’s type and that subclass provides the reflected method for the operation, this method will be called before the left operand’s non-reflected method. This behavior allows subclasses to override their ancestors’ operations.
Putting this into Pythonesque pseudocode, x * y is evaluated something like this:
if type(y) is type(x):
return x.__mul__(y)
elif type(y) is a subclass of type(x):
try y.__rmul__(x)
otherwise x.__mul__(y)
else:
try x.__mul__(y)
otherwise y.__rmul__(x)
Of course you can also determine the calling order dynamically by creating separate types whose methods just print their names and 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()
for x, y in itertools.permutations((Base, Derived, Unrelated), 2):
print('{} * {}: '.format(x.__name__, y.__name__), end='')
x() * y()
What about with built in types as well?
Exactly the same rules. Since Base is not a subclass of either int or float, and neither int nor float knows how to multiply by it, they'll both call Base.__rmul__. And so will any other unrelated type you throw at 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 is that I'm getting different results from 1.5 * myObj and myObj * 1.5
There are a number of reasons for that:
Your __mul__ and __rmul__ code don't do the same thing.
You inherited from float.
You inherited from some builtin or extension type that handles float multiplication at the C-API level and isn't designed to allow overrides in subclasses.
You created a classic class instead of a new-style class.
You made a typo in one of the names.
…
Is there any way to use infix operators (like +,-,*,/) as higher order functions in python without creating "wrapper" functions?
def apply(f,a,b):
return f(a,b)
def plus(a,b):
return a + b
# This will work fine
apply(plus,1,1)
# Is there any way to get this working?
apply(+,1,1)
You can use the operator module, which has the "wrapper" functions written for you already.
import operator
def apply(f,a,b):
return f(a,b)
print apply(operator.add,1,1)
Result:
2
You can also define the wrapper using lambda functions, which saves you the trouble of a standalone def:
print apply(lamba a,b: a+b, 1, 1)
Use operator module and a dictionary:
>>> from operator import add, mul, sub, div, mod
>>> dic = {'+':add, '*':mul, '/':div, '%': mod, '-':sub}
>>> def apply(op, x, y):
return dic[op](x,y)
...
>>> apply('+',1,5)
6
>>> apply('-',1,5)
-4
>>> apply('%',1,5)
1
>>> apply('*',1,5)
5
Note that you can't use +, -, etc directly as they are not valid identifiers in python.
You can use the operator module this way:
import operator
def apply(op, a, b):
return op(a, b)
print(apply(operator.add, 1, 2))
print(apply(operator.lt, 1, 2))
Output:
3
True
The other solution is to use a lambda function, but "there should be one -- and preferably only one -- obvious way to do it", so I prefer to use the operator module
you can use anonymous function : apply(lambda x,y : x + y, 1,1)
# Is there any way to get this working?
apply(+,1,1)
No. As others have already mentioned, there are function forms of all of the operators in the operator module. But, you can't use the operators themselves as that is a SyntaxError and there is no way to dynamically change python's core syntax. You can get close though using dictionaries and passing strings:
_mapping = {'+':operator.add}
def apply(op,*args):
return _mapping[op](*args)
apply('+',1,1)
It is possible to give the operators +, -, *, and / special behavior for a class using magic methods, you can read about this here: http://www.rafekettler.com/magicmethods.html
This isn't exactly what you were asking for because this still requires the creation of a method for each operator, but it does allow you to use the operators by symbol in your code. Note that I don't think this is better than the other methods, it is just an illustration of how you can define behavior for operators:
class Prefix(object):
def __add__(self, other):
""" Prefix() + (a, b) == a + b """
return other[0] + other[1]
def __sub__(self, other):
""" Prefix() - (a, b) == a - b """
return other[0] - other[1]
def __mul__(self, other):
""" Prefix() * (a, b) == a * b """
return other[0] * other[1]
def __div__(self, other):
""" Prefix() / (a, b) == a / b """
return other[0] / other[1]
And examples:
>>> prefix = Prefix()
>>> prefix + (12, 3)
15
>>> prefix - (12, 3)
9
>>> prefix * (12, 3)
36
>>> prefix / (12, 3)
4
Of course this method can't be used for a more complex prefix equation like * / 6 2 5 because there is no way to define behavior for adjacent operators, which will always give a SyntaxError (except for a few special cases where + or - are interpreted as making the next element positive or negative).