Is it possible to overload the ternary operator in python? Basically what I want is something like:
class A(object):
def __ternary__(self, a, c):
return a + c
a = A()
print "asdf" if a else "fdsa" # prints "asdffdsa"
I'm trying to implement a symbolic package and basically want something that can do things like:
sym = Symbol("s")
result = 1 if sym < 3 else 10
print result.evaluate(sym=2) # prints 1
print result.evaluate(sym=4) # prints 10
Edit: Let me put out a bit more complex example to show how this could be layered upon.
sym = Symbol("s")
result = 1 if sym < 3 else 10
...
something_else = (result+1)*3.5
...
my_other_thing = sqrt(something_else)
print my_other_thing.evaluate(sym=2) # prints sqrt(7) or rather the decimal equivalent
The point is, I don't need to just be able to late evaluate the one ternary operator, I need to take the result and do other symbolic stuff with that before finally evaluating. Furthermore, my code can do partial evaluations where I give it a few bindings and it returns another symbolic expression if it can't evaluate the full expression.
My backup plan is just to directly use the ternary class taking 3 expressions objects that I would need to make anyway. I was just trying to hide the generation of this class with an operator overload. Basically:
a = TernaryOperator(a,b,c)
# vs
b = a if b else c
look at the sympy module; it already does this
for simple comparison, write A.__eq__ and A.__lt__ methods and use the total_ordering class decorator; this should be sufficient for comparing two As or an A and a constant
write it as a lambda,
result = lambda sym: 1 if sym < 3 else 10
print(result(2)) # => 1
print(result(4)) # => 10
Overload the comparison operators instead (something you probably needed to do anyway):
class A(object):
def __lt__(self, other):
return self.value() < other.value() # Replace with your own implementation of <
Then, use lambda functions to achieve the delayed evaluation you desire:
sym = Symbol("s")
result = lambda s: 1 if s < 3 else 10
sym.set(2)
print result(sym) # prints 1
sym.set(4)
print result(sym) # prints 10
(I don't think you can overload the assignment operator, as it doesn't actually perform an operation on any object, but rather on a variable.)
Related
A protected division is a normal division but when you divide by 0 it returns a fixed constant (usually 1).
def protected_div(x, y):
if y == 0:
return 1
return x/y
Is there a way to use this as an operator on sympy (For example replacing the standard division)?
Here is an example of what I want:
>>> import sympy as sym
>>> x = sym.Symbol('x')
>>> expr = 1/x #(protected division goes here?)
>>> expr.subs(x, 0)
1
The division has to be protected at evaluation time.
EDIT 1:
What I've tried:
1.
Using sym.lambidify with the modules parameter set:
>>> x = sym.Symbol('x')
>>> expr = 1/x
>>> lamb = sym.lambdify(x, expr, modules={'/':protected_div})
>>> print(lamb(0))
ZeroDivisionError: 0.0 cannot be raised to a negative power
This does not work because sympy converts 1/x to x**(-1) when lambidifying. I tried overriding the power operator but I don't know the function name. I've tried 'Pow', 'pow', '**' and none worked.
However if i declare the expression as expr = 1.0/x it actually does not convert to a negative power, however it does not use my custom division function. I think these types of functions are not overridable using the module parameter.
2.
#Zaz suggestion:
class floatsafe(float):
def __truediv__(self, __x):
if __x == 0:
return floatsafe(1)
return super().__truediv__(__x)
x = sym.Symbol('x')
expr = floatsafe(1)/x
print(expr.subs(x, floatsafe(0)))
Returns
zoo
Which is complex infinity.
I tried combining this approach with sym.lambdify, but the dividend is converted to a float after I lambdify the function.
In the case that the dividend is variable it also does not work:
x = sym.Symbol('x')
expr = x/0.0
a = sym.lambdify(x, expr, modules={'/':floatsafe.__truediv__})
print(inspect.getsource(a))
print(a(floatsafe(0)))
Outputs
def _lambdifygenerated(x):
return nan*x
nan
EDIT: There seems to some confusion around why I'd want that. It's for a genetic programming algorithm using sympy. A protected division is a common operator in GP so that the created solutions are valid.
The regular mathematics we use on the day-to-day is a ring on the set of real numbers, ℝ: The properties of a ring are that you have two operations (such as multiplication and addition) and one of them (such as addition) will always produce another number within the set.
You can create a more specific notion of a field (such that both operations will always produce another member in the set) by removing 0 or expanding the set to the hyperreals.
My point being, without knowing what problem exactly you're trying to solve, I would guess that instead of redefining division, it makes more sense to redefine the number system that you're using: For whatever reason, you have some system of numbers that should return 1 when divided by zero, so why not create a subclass of float, for example?
class floatD01(float):
def __truediv__(self, divisor):
if divisor == 0:
return 1
return self/divisor
You may also want to scan help(float) for any other methods related to division that you may want to change such as __divmod__, __floordiv__ (7//3 == 2), etc, and have a hard think about how you want this new mathematical group that you're creating to work and why.
Other options that may potentially be more robust would be to go nuclear and try catching all ZeroDivisionErrors and replace them with one (either by modifying the class) or within whatever code you're running or, if appropriate, implementing something like what the language R extensively uses: NA values. I'm sure there's some way (I believe in numpy) to do something along the lines of: C = [1/3, 2/2, 3/1, 4/0] # == [1/3, 2/2, 3/1, NA] sum(C) = 4.333
The solution was pretty simple actually, although I was not able to actualy overload the division operator all I had to do was create a sympy function for the protected division and use that instead.
class protected_division(sym.Function):
#classmethod
def eval(cls, x, y):
if y.is_Number:
if y.is_zero:
return sym.S.One
else:
return x/y
Then just use that in an expression:
>>> expr = protected_division(1, sym.Symbol('x'))
protected_division(1, x)
>>> expr.subs(sym.Symbol('x'), 0)
1
>>> expr.subs(sym.Symbol('x'), 3)
1/3
I did not find out how to make the class tell sym.lambdify what to do in case of a "lambdification", but you can use the modules parameters for that:
>>> def pd(x, y):
... if y == 0:
... return 1
... return x/y
...
>>> l = sym.lambdify(sym.Symbol('x'), expr, modules={'protected_division': pd})
>>> l(3)
1.6666666666666667
>>> l(0)
1
Let's say I have operator A and operator B which act on f(x) = 2x for example. How do I create a function that says whether A(B(f(x))) == B(A(f(x))) in python?
Here is my attempt:
#Commutation: Creating a function that checks whether operators A and B commutate on some dummy function f(x) = 2*x
#[A,B](2x) =?= 0
def commutate(A,B):
f = lambda x: 2*x
if lambda x: A(B(f)) - B(A(f)) == 0:
print('A and B commute!')
else:
print('A and B do not commute!')
A = lambda x: f(x)**2
B = lambda x: np.log(f(x))
commutate(A,B)
The issue is that I'm always getting that the operators A and B commute, even when giving Operators that don't. I suspect this might have to do with the fact that I can't Define operators like that in python?
In general, it is not possible, based on Rice theorem. Because you desire to check a non-trivial property for two pieces of code, i.e., the property is commutativeness and piece of code here means functions. Hence, it proves that deciding that "any given f and g functions are commutative" is undecidable. Therefore, you can't write such a function to check the commutativeness for two functions.
In your code you have the line
if lambda x: A(B(f)) - B(A(f)) == 0:
In this line you are generating a lambda that is calling the operators on the address of f rather than a result of calling f. Also, you are not calling the lambda that you define in the if statement, so you are checking if the address of the lambda function is True/False which is not what you are looking for.
Lambdas are just functions, but you could test if the operators are commutative on a specific value:
def commutate(A, B, value):
f = lambda x: 2 * x
if A(B(f(value))) == B(A(f(value))):
print(f"A and B commute on value {value}!")
else:
print(f"A and B do not commute on value {value}!")
Very often I find myself writing a ternary operator equivalent to the following
var = a if returnsBool(a) else b
with returnsBool returning a boolean value depending on the value of a.
When a is lengthier variable it starts to look ugly and 'unpythonic'. Is there a way to reference a in the conditional part (returnsBool(a)) of the statement so you don't have to write a twice?
Or is there a better approach for this case, which is also useful for list comprehensions?
You can use the := "walrus" assignment operator that was introduced in Python 3.8:
def returnsBool(a):
return bool(a)
reallylengthiervariablename = 42
b = 2
var = a if returnsBool(a := reallylengthiervariablename) else b
print(f'{var=}') # -> var=42
As long as a itself cannot be a "falsy" value, you could change your returnsBool to return a / None instead of True / False.
Then you could write:
var = maybe(a) or b
Otherwise, defining your own ternary seems like the best bet:
def conditional(func, a, b):
return a if func(a) else b
And you could customize it for specific conditions using partial:
from functools import partial
some_cond = partial(conditional, returnsBool)
vars = [some_cond(a, b) for a, b in whatever]
Here's a not-very-idiomatic way of doing it, but it works; the next function can take a second argument which is returned in case the first argument is an empty iterator.
>>> def is_even(x): return x % 2 == 0
...
>>> very_long_variable_name = 12
>>> next(filter(is_even, [very_long_variable_name]), 'default')
12
>>> very_long_variable_name = 13
>>> next(filter(is_even, [very_long_variable_name]), 'default')
'default'
If you find yourself having to do this often, it may be worth writing a helper function, so that you can write e.g. if_else(is_even, very_long_variable_name, 'default').
def if_else(predicate, a, b):
return a if predicate(a) else b
How do I use pre-increment/decrement operators (++, --), just like in C++?
Why does ++count run, but not change the value of the variable?
++ is not an operator. It is two + operators. The + operator is the identity operator, which does nothing. (Clarification: the + and - unary operators only work on numbers, but I presume that you wouldn't expect a hypothetical ++ operator to work on strings.)
++count
Parses as
+(+count)
Which translates to
count
You have to use the slightly longer += operator to do what you want to do:
count += 1
I suspect the ++ and -- operators were left out for consistency and simplicity. I don't know the exact argument Guido van Rossum gave for the decision, but I can imagine a few arguments:
Simpler parsing. Technically, parsing ++count is ambiguous, as it could be +, +, count (two unary + operators) just as easily as it could be ++, count (one unary ++ operator). It's not a significant syntactic ambiguity, but it does exist.
Simpler language. ++ is nothing more than a synonym for += 1. It was a shorthand invented because C compilers were stupid and didn't know how to optimize a += 1 into the inc instruction most computers have. In this day of optimizing compilers and bytecode interpreted languages, adding operators to a language to allow programmers to optimize their code is usually frowned upon, especially in a language like Python that is designed to be consistent and readable.
Confusing side-effects. One common newbie error in languages with ++ operators is mixing up the differences (both in precedence and in return value) between the pre- and post-increment/decrement operators, and Python likes to eliminate language "gotcha"-s. The precedence issues of pre-/post-increment in C are pretty hairy, and incredibly easy to mess up.
Python does not have pre and post increment operators.
In Python, integers are immutable. That is you can't change them. This is because the integer objects can be used under several names. Try this:
>>> b = 5
>>> a = 5
>>> id(a)
162334512
>>> id(b)
162334512
>>> a is b
True
a and b above are actually the same object. If you incremented a, you would also increment b. That's not what you want. So you have to reassign. Like this:
b = b + 1
Many C programmers who used python wanted an increment operator, but that operator would look like it incremented the object, while it actually reassigns it. Therefore the -= and += operators where added, to be shorter than the b = b + 1, while being clearer and more flexible than b++, so most people will increment with:
b += 1
Which will reassign b to b+1. That is not an increment operator, because it does not increment b, it reassigns it.
In short: Python behaves differently here, because it is not C, and is not a low level wrapper around machine code, but a high-level dynamic language, where increments don't make sense, and also are not as necessary as in C, where you use them every time you have a loop, for example.
While the others answers are correct in so far as they show what a mere + usually does (namely, leave the number as it is, if it is one), they are incomplete in so far as they don't explain what happens.
To be exact, +x evaluates to x.__pos__() and ++x to x.__pos__().__pos__().
I could imagine a VERY weird class structure (Children, don't do this at home!) like this:
class ValueKeeper(object):
def __init__(self, value): self.value = value
def __str__(self): return str(self.value)
class A(ValueKeeper):
def __pos__(self):
print 'called A.__pos__'
return B(self.value - 3)
class B(ValueKeeper):
def __pos__(self):
print 'called B.__pos__'
return A(self.value + 19)
x = A(430)
print x, type(x)
print +x, type(+x)
print ++x, type(++x)
print +++x, type(+++x)
TL;DR
Python does not have unary increment/decrement operators (--/++). Instead, to increment a value, use
a += 1
More detail and gotchas
But be careful here. If you're coming from C, even this is different in python. Python doesn't have "variables" in the sense that C does, instead python uses names and objects, and in python ints are immutable.
so lets say you do
a = 1
What this means in python is: create an object of type int having value 1 and bind the name a to it. The object is an instance of int having value 1, and the name a refers to it. The name a and the object to which it refers are distinct.
Now lets say you do
a += 1
Since ints are immutable, what happens here is as follows:
look up the object that a refers to (it is an int with id 0x559239eeb380)
look up the value of object 0x559239eeb380 (it is 1)
add 1 to that value (1 + 1 = 2)
create a new int object with value 2 (it has object id 0x559239eeb3a0)
rebind the name a to this new object
Now a refers to object 0x559239eeb3a0 and the original object (0x559239eeb380) is no longer refered to by the name a. If there aren't any other names refering to the original object it will be garbage collected later.
Give it a try yourself:
a = 1
print(hex(id(a)))
a += 1
print(hex(id(a)))
In python 3.8+ you can do :
(a:=a+1) #same as ++a (increment, then return new value)
(a:=a+1)-1 #same as a++ (return the incremented value -1) (useless)
You can do a lot of thinks with this.
>>> a = 0
>>> while (a:=a+1) < 5:
print(a)
1
2
3
4
Or if you want write somthing with more sophisticated syntaxe (the goal is not optimization):
>>> del a
>>> while (a := (a if 'a' in locals() else 0) + 1) < 5:
print(a)
1
2
3
4
It will return 0 even if 'a' doesn't exist without errors, and then will set it to 1
Python does not have these operators, but if you really need them you can write a function having the same functionality.
def PreIncrement(name, local={}):
#Equivalent to ++name
if name in local:
local[name]+=1
return local[name]
globals()[name]+=1
return globals()[name]
def PostIncrement(name, local={}):
#Equivalent to name++
if name in local:
local[name]+=1
return local[name]-1
globals()[name]+=1
return globals()[name]-1
Usage:
x = 1
y = PreIncrement('x') #y and x are both 2
a = 1
b = PostIncrement('a') #b is 1 and a is 2
Inside a function you have to add locals() as a second argument if you want to change local variable, otherwise it will try to change global.
x = 1
def test():
x = 10
y = PreIncrement('x') #y will be 2, local x will be still 10 and global x will be changed to 2
z = PreIncrement('x', locals()) #z will be 11, local x will be 11 and global x will be unaltered
test()
Also with these functions you can do:
x = 1
print(PreIncrement('x')) #print(x+=1) is illegal!
But in my opinion following approach is much clearer:
x = 1
x+=1
print(x)
Decrement operators:
def PreDecrement(name, local={}):
#Equivalent to --name
if name in local:
local[name]-=1
return local[name]
globals()[name]-=1
return globals()[name]
def PostDecrement(name, local={}):
#Equivalent to name--
if name in local:
local[name]-=1
return local[name]+1
globals()[name]-=1
return globals()[name]+1
I used these functions in my module translating javascript to python.
In Python, a distinction between expressions and statements is rigidly
enforced, in contrast to languages such as Common Lisp, Scheme, or
Ruby.
Wikipedia
So by introducing such operators, you would break the expression/statement split.
For the same reason you can't write
if x = 0:
y = 1
as you can in some other languages where such distinction is not preserved.
Yeah, I missed ++ and -- functionality as well. A few million lines of c code engrained that kind of thinking in my old head, and rather than fight it... Here's a class I cobbled up that implements:
pre- and post-increment, pre- and post-decrement, addition,
subtraction, multiplication, division, results assignable
as integer, printable, settable.
Here 'tis:
class counter(object):
def __init__(self,v=0):
self.set(v)
def preinc(self):
self.v += 1
return self.v
def predec(self):
self.v -= 1
return self.v
def postinc(self):
self.v += 1
return self.v - 1
def postdec(self):
self.v -= 1
return self.v + 1
def __add__(self,addend):
return self.v + addend
def __sub__(self,subtrahend):
return self.v - subtrahend
def __mul__(self,multiplier):
return self.v * multiplier
def __div__(self,divisor):
return self.v / divisor
def __getitem__(self):
return self.v
def __str__(self):
return str(self.v)
def set(self,v):
if type(v) != int:
v = 0
self.v = v
You might use it like this:
c = counter() # defaults to zero
for listItem in myList: # imaginary task
doSomething(c.postinc(),listItem) # passes c, but becomes c+1
...already having c, you could do this...
c.set(11)
while c.predec() > 0:
print c
....or just...
d = counter(11)
while d.predec() > 0:
print d
...and for (re-)assignment into integer...
c = counter(100)
d = c + 223 # assignment as integer
c = c + 223 # re-assignment as integer
print type(c),c # <type 'int'> 323
...while this will maintain c as type counter:
c = counter(100)
c.set(c + 223)
print type(c),c # <class '__main__.counter'> 323
EDIT:
And then there's this bit of unexpected (and thoroughly unwanted) behavior,
c = counter(42)
s = '%s: %d' % ('Expecting 42',c) # but getting non-numeric exception
print s
...because inside that tuple, getitem() isn't what used, instead a reference to the object is passed to the formatting function. Sigh. So:
c = counter(42)
s = '%s: %d' % ('Expecting 42',c.v) # and getting 42.
print s
...or, more verbosely, and explicitly what we actually wanted to happen, although counter-indicated in actual form by the verbosity (use c.v instead)...
c = counter(42)
s = '%s: %d' % ('Expecting 42',c.__getitem__()) # and getting 42.
print s
There are no post/pre increment/decrement operators in python like in languages like C.
We can see ++ or -- as multiple signs getting multiplied, like we do in maths (-1) * (-1) = (+1).
E.g.
---count
Parses as
-(-(-count)))
Which translates to
-(+count)
Because, multiplication of - sign with - sign is +
And finally,
-count
A straight forward workaround
c = 0
c = (lambda c_plusplus: plusplus+1)(c)
print(c)
1
No more typing
c = c + 1
Also, you could just write
c++
and finish all your code and then do search/replace for "c++", replace with "c=c+1". Just make sure regular expression search is off.
Extending Henry's answer, I experimentally implemented a syntax sugar library realizing a++: hdytto.
The usage is simple. After installing from PyPI, place sitecustomize.py:
from hdytto import register_hdytto
register_hdytto()
in your project directory. Then, make main.py:
# coding: hdytto
a = 5
print(a++)
print(++a)
b = 10 - --a
print(b--)
and run it by PYTHONPATH=. python main.py. The output will be
5
7
4
hdytto replaces a++ as ((a:=a+1)-1) when decoding the script file, so it works.
Assume I have a function
def multiply_by(x, multiplier):
return x * multiplier
How can I create a copy of that function and fix the multiplier in that function?
multiply_by_5 = multiply_by? <-- here I need python magic
such that multiply_by_5 would have only one argument x and the multiplier would be 5? So that
multiply_by_5(2)
10
Is there a way in Python 2.7 to do that?
You can use functools.partial with keyword argument:
>>> def multiply_by(x, multiplier):
... return x * multiplier
...
>>> from functools import partial
>>> multiply_by_5 = partial(multiply_by, multiplier=5)
>>> multiply_by_5(2)
10
functools.partial is made exactly for this.
you can use it like
import functools
multiply_by_5=functools.partial(multiply_by,multiplier=5)
As suggested by #niemmi's answer, functools.partial is probably the way to go.
However, similar work can be done using curried functions:
def multiply_by(multiplier):
def multiply(x):
return multiplier * x
return multiply
>>> multiply_by_5 = multiply_by(5) # no magic
>>> multiply_by_5(2)
10
Or using the lambda syntax:
def multiply_by(multiplier):
return lambda x: multiplier * x
Note that partial is more succinct, more efficient, and more directly express your intent in a standard way. The above technique is an example of the concept called closure, which is means that a function defined in inner scope may refer to variables defined in enclosing scopes, and "close" over them, remembering them, and even mutating them.
Since this technique is more general, it might take the reader of your code more time to understand what exactly do you mean in your code, since your code may be arbitrarily complicated.
Specifically for multiplication (and other operators) partial can be combined with operator.mul:
>>> import functools, operator
>>> multiply_by_5 = functools.partial(operator.mul, 5)
>>> multiply_by_5(2)
10
Here's an alternative that doesn't use functools.partial. Instead we define a function inside a function. The inner function "remembers" any of the local variables of the outer function that it needs (including the outer function's arguments). The magic that makes this happen is called closure.
def multiply_factory(multiplier):
def fixed_multiply(x):
return x * multiplier
return fixed_multiply
multiply_by_3 = multiply_factory(3)
multiply_by_5 = multiply_factory(5)
for i in range(5):
print(i, multiply_by_3(i), multiply_by_5(i))
output
0 0 0
1 3 5
2 6 10
3 9 15
4 12 20
If you want, you can use your existing multiply_by function in the closure, although that's slightly less efficient, due to the overhead of an extra function call. Eg:
def multiply_factory(multiplier):
def fixed_multiply(x):
return multiply_by(x, multiplier)
return fixed_multiply
That can be written more compactly using lambda syntax:
def multiply_factory(multiplier):
return lambda x: multiply_by(x, multiplier)
If you cannot change the multiply_by() function, the simplest and perhaps best way is probably
def multiply_by_5(x):
return multiply_by(x, 5)
You can also use lambda if you really want a one-liner.
However, you may want to change your first function to
def multiply_by(x, multiplier = 5):
return x * multiplier
Then you can do either of these:
print(multiply_by(4, 3))
12
print(multiply_by(2))
10