Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Strange behavior: ternary operator for functions

Here is a simplified example of my problem. I thought that these functions would have exactly the same behavior:

def f1(l):
    if type(l[0][0])==list: f=lambda x:x[0][0]
    else: f=lambda x:x[0]
    l.sort(key=f,reverse=True)

def f2(l):
    f=lambda x:x[0][0] if type(l[0][0])==list else lambda x:x[0]
    l.sort(key=f,reverse=True)

l=[[1,2],[3,4]]

But in reality f1(l) works fine when f2(l) collapses with the exception:

IndexError: list index out of range

So the question is why is it so and is it possible to use ternary operator that returns one of the functions at all?

like image 525
Nik Avatar asked Feb 07 '15 05:02

Nik


People also ask

Can you use functions in ternary operator?

Nope, you can only assign values when doing ternary operations, not execute functions.

How do you write 3 conditions in a ternary operator?

The conditional (ternary) operator is the only JavaScript operator that takes three operands: a condition followed by a question mark ( ? ), then an expression to execute if the condition is truthy followed by a colon ( : ), and finally the expression to execute if the condition is falsy.

Why ternary operator is better than if-else?

There's a different emphasis: An if / else statement emphasises the branching first and what's to be done is secondary, while a ternary operator emphasises what's to be done over the selection of the values to do it with.

Can ternary operator have two conditions?

In the above syntax, we have tested 2 conditions in a single statement using the ternary operator. In the syntax, if condition1 is incorrect then Expression3 will be executed else if condition1 is correct then the output depends on the condition2.


1 Answers

lambda has the lowest precedence among operators. This is why Python parses that line as

f = lambda x: (x[0][0] if type(l[0][0]) == list else lambda x: x[0])

The fix is to wrap individual lambdas in parentheses:

f = (lambda x: x[0][0]) if type(l[0][0]) == list else (lambda x: x[0])

That said, type(l[0][0]) == list is kinda wrong, isinstance(l[0][0], list) would be the best way (it also handles subclasses of list).

like image 62
vaultah Avatar answered Nov 03 '22 16:11

vaultah