2

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
5
  • 1
    Wouldn't it be better to overload the comparison operators (and convert-to-bool operator; don't know what the proper Python term is) instead? Commented Feb 18, 2015 at 3:24
  • I think you have the comparison backwards on your example - should be if sym < 3 Commented Feb 18, 2015 at 3:27
  • @HughBothwell Good call Commented Feb 18, 2015 at 3:29
  • @AasmundEldhuset How would you implement what I'm trying to do then? If I understand correct, what you're suggesting would get evaluated at the result=... line instead of the print lines. Commented Feb 18, 2015 at 3:30
  • Use lambda functions - see my answer. Commented Feb 18, 2015 at 3:36

2 Answers 2

1
  1. look at the sympy module; it already does this

  2. 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

  3. write it as a lambda,

    result = lambda sym: 1 if sym < 3 else 10
    print(result(2))    # => 1
    print(result(4))    # => 10
    
Sign up to request clarification or add additional context in comments.

2 Comments

Your lambda operates on the integers 2 and 4.
Yes, it does; per his example, result.evaluate(sym=2), this may be sufficient for his needs.
0

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.)

1 Comment

it's actually the ternary operator I was hoping to overload (not the assignment operator) but I have a feeling that you just can't overload it, which is too bad

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.