Moca
Moca

Reputation: 25

Lambda expression producing a SyntaxError

I am looking for an lambda expression to print an integer if a given string is in a given sentence separated by /. This is the statement I wrote:

hunter = udf(lambda x : 'opened' in x.lower().split() print(10) elif 'clickedurl' in x.lower().split() print(20)  else print("null"))
s= it/is/opened/memory/tae
hunter(s)

I am getting the following error

 File "/home/main.py", line 1                                                                                         
    hunter = udf(lambda x : 'opened' in x.lower().split() print(10) elif 'clickedurl' in x.lower().split() print 20  el
se print("null"))                                                                                                      
                                                              ^                                                        
SyntaxError: invalid syntax 

Upvotes: 0

Views: 2094

Answers (1)

abarnert
abarnert

Reputation: 365915

You have multiple syntax errors in your code, and you have to fix all of them.


First, lambda expressions—like all expressions—cannot have statements in them, only expressions.

And that includes Python 2's print statement, which you appear to be using.

If you want to write a function that includes a statement, you need to use a def statement, not a lambda expression.


Second, if you were trying to write an if-else expression, you got the syntax for that wrong. You need to put the true-expression first, then if, then the condition to check, then else, then the false-expression.

You appear to have been trying to put the condition first, right before the true-expression:

'opened' in x.lower().split() print(10)

You can't do that. And that's where your first SyntaxError, the one you're asking about, comes from.


Third, you cannot use elif in an if-else expression. You'd have to write it into an if-else expression with another if-else expression as the false-value.

Which is going to look horrible. If you find yourself needing that, you almost certainly want to break it out into an if statement instead.


Also, while it isn't illegal, it's highly misleading to use an if-else expression for its side effects.. if-else expressions are about picking one value or another, not about running one set of side effects or another. If the latter is what you want, you want an if statement.

And the same is true for lambda. That's about defining functions that compute values; a function that's only called for its side effects should almost always be a def.


So, what you want is this:

def thingy(x):
    if 'opened' in x.lower().split():
        print(10)
    elif 'clickedurl' in x.lower().split():
        print(20)
    else:
        print('null')

hunter = udf(thingy)

And notice that this gives you the opportunity to improve things (both readability and performance) by avoiding some repetition:

def thingy(x):
    words = x.lower().split()
    if 'opened' in words:
        print(10)
    elif 'clickedurl' words:
        print(20)
    else:
        print('null')

Although of course you don't want to use names like x and thingy. I have no idea what any of these things represent, but surely you do.

And finally, I don't know what that udf function is, but I can't imagine it returning anything useful when called with a function that always returns None, so I'll bet you have more problems beyond these, but hopefully you can solve them from here.


And of course once you fix all of that, the next line is also a syntax error:

s= it/is/opened/memory/tae

This is attempting to divide a bunch of things. Even if it, opened, memory, and tae are all variables with relevant values, is certainly isn't, because it's a built-in operator, so you can't divide anything by it.

You probably wanted a string here.

Also, because you're calling split() without any argument, that's only going to split things separated by whitespace. So, either you wanted split('/') above, or you wanted whitespace here.

So:

s = 'it is opened memory tae'

If you really wanted to make this one giant expression, it's possible, but it's going to be very, very ugly.

First, you have to replace that print statement with a function call. Of course you could from __future__ import print_function, but otherwise, you need to write a function that does what you want, or use one that already exists.

Second, you either need an if-else inside an if-else as the argument to that function, or you need to call that function in each branch of an if-else in an if-else. I think the first is slightly less horrible.

So:

lambda x: sys.stdout.write(
    str(10 if 'opened' in x.lower().split() else (
             20 if 'clickedurl' in x.lower().split() else 'null'))
    + '\n')

And of course inside an expression, whitespace doesn't matter, so you can freely rewrite that to be even uglier if you want:

lambda x:sys.stdout.write(str(10 if 'opened' in x.lower().split() else(20 if 'clickedurl' in x.lower().split() else 'null'))+ '\n')

… or:

lambda x: sys.stdout.write(str
       (10 
  if 'opened' in x.
            lower
           (
         ).
     split() else (20
   if 'clickedurl' in x.lower().split() else 'null'))+ '\n')

I can't imagine why you'd want the latter, but then I can't imagine why you'd want the former either, and yet you seemed to be trying to write something as much like that as possible, so… go for it.

Upvotes: 3

Related Questions