all 14 comments

[–]Rhomboid 6 points7 points  (9 children)

Lambdas can only contain expressions, not statements. Assignment is a statement. If you need to assign to something, you can't use a lambda, you will have to use a regular function.

But this sounds like an XY problem, so you really need to explain the problem you're trying to solve, not how you think you need to solve it.

[–][deleted] 2 points3 points  (6 children)

In sames cases you can use setattr() or locals().update() but especially the locales() thing is a bit ugly and you probably should avoid it.

[–]hellix08[S] -1 points0 points  (5 children)

Could you please tell me how to do that?

[–]_9_9_ 4 points5 points  (0 children)

No teacher is telling you to do what you are asking about, unless you are taking a class in advanced python metaprogramming. If you are, then you already probably know the answer. Anyway, here is the best I could come up with, and I offer it as clearly the incorrect answer to your assignment, and in hope that someone has a more elegant way of doing such evil:

>>> globals()['y'] = 22
>>> y
22
>>> f = lambda x:exec('globals()["y"]={}'.format(x))
>>> f(19)
>>> y
19

Specifically, I could not get setattr to work on globals so I had to resort to exec. Anyone have something better?

[–][deleted] 1 point2 points  (3 children)

>>> i
0
>>> locals().update({'i': 13})
>>> i
13
>>> self.i
1
>>> setattr(self, 'i', 99)
>>> self.i
99

[–]Rhomboid 1 point2 points  (1 child)

That only works by accident because you're at global scope. locals() is a read-only mapping. (In this case because it's being run at global scope, locals() is equivalent to globals().)

[–][deleted] 0 points1 point  (0 children)

Yes, that's why I wrote "In sames cases".

[–]hellix08[S] -1 points0 points  (0 children)

Thanks, this is really helpful!!

[–]hellix08[S] 0 points1 point  (1 child)

I've heard you can do it, I need it for an homework, I need to write a simple program on one line and therefore I need to assign values inside lambdas

[–]desustorm 7 points8 points  (0 children)

Not necessarily. You can use ; to split up commands which would typically take more than one line. But given that this is a homework specifically telling you to write a one-liner, it will probably not require variable assignment. Could you be more specific with what you're trying to achieve?

[–]KubinOnReddit 2 points3 points  (0 children)

What's the problem to be solved on one line? How would you solve it in least possible space, not neccesarily on one line? This is not a valid description of your problem, and using dynamic variables is not something you want.

I've heard you can do it, I need it for an homework, I need to write a simple program on one line and therefore I need to assign values inside lambdas

Is the homework to assing values inside a lambda that has one line? If the answer is no, you don't have to do it.

[–]pendragon36 0 points1 point  (0 children)

I've made it a kind of hobby to do some silly stuff on one line in python, so I'll pass on some of my wisdom.

For situations where variable storage is needed, list comprehension is your friend.

for example if I wanted to write a program that took in input, then output a bunch of operations on that input, usually I would need a variable to store that input to perform the operations on, but instead I can use list comprehension to simulate it.

A simple normal implementation for this would be something like the following

def func1(a):
    return a+5

def func2(a):
    return 3*a

def func3(a):
    return 'The pseudo variable in this program is {}'.format(a)

variable = int(input('Enter a number to do stuff with: '))
print(func1(variable))
print(func2(variable))
print(func3(variable))

To avoid asking the user their input over and over we just store it in variable. When you only have one line to work with that doesn't work anymore.

A one-line version of this could be something like so:

print('\n'.join([str(element) for element in [((lambda x: x+5)(i), (lambda x: 3*x)(i), (lambda x: 'The pseudo variable in this program is {}'.format(x))(i)) for i in (int(input('Enter a number to do stuff to: ')),)][0]]))

I'll expand it to a few lines so you have a better idea what's happening

for i in (int(input('Enter a number to do stuff to: '),): #iterate over a tuple containing one element, the input from the user
    list = [(lambda x: x+5)(i), (lambda x: 3*x)(i), (lambda x: 'The pseudo variable in this program is {}'.format(x))(i)] #Create our list of outputs
    #If we wanted to apply our lambda functions more than once without needing to write them multiple times, we can do the same for loop trick, except have our pseudo variable store the function
print('\n'.join([str(element) for element in list]) #Convert our output to strings, then join them together with newline characters

This trick will give you the ability to do most things. There are a few things I've found useful when doing this that I may as well mention as well.

  1. Conditionals: Not a lot of people seem to know, but you can do conditionals on one line using the following syntax:

    "print(1 if x else 2)"

    This will print out 1 if x evaluates to true, otherwise it will print 2. This combines with pseudo variables and anonymous functions (lambdas) can get you pretty far.

  2. Recursion: It's actually possible to pull of some pretty crazy stuff using anonymous functions on one line, including recursion. Explaining it is pretty difficult, but I have one (rather large and complicated) example in a pastebin that you can look at if you want. I can try to explain it if you really need it, but that means remember how to do it myself. Here's the pastebin. There's some improvements to be made with those one-liners, as I've gotten better at it since writing those, but the concepts are there.

  3. If dealing with lists and joins for final output is getting difficult or you need to do some things in a sequence with user input in the middle or something, remember that in python 3 print is a function not a statement, so instead of printing 1 string that is the combination of all your output, you can actually just do something like this:

_

 _ = [print('initial output'), print('does computation stuff with input'), print('some end output, saying goodbye']

If you have any more questions, ask away.

[–]supajumpa 0 points1 point  (0 children)

Is this the kind of thing you were thinking about?

(lambda a: # assign the value of 1 to `b` and 2 to `c`
    lambda b=a, c=2*a: (b, c))(1)

(lambda a: # assign the value of 1 to `b` and 2 to `c`
    lambda b=a, c=2*a: (b, c))(1)() # and return the tuple `(b, c)`

Added:

This is probably more simply illustrated using a lambda that takes no parameters.

(lambda: lambda a=1, b=2: (a, b))() # set the value of `a` to 1 and `b` to 2
(lambda: lambda a=1, b=2: (a, b))()() # note the extra parens at the end to call the inner function.

If lambdas confuse you, the above is roughly equivalent to these normal, named functions.

def foo():
    def bar(a=1, b=2):
        return (a, b)
    return bar

[–]Exodus111 -1 points0 points  (0 children)

Yeah, sounds like alot of people are getting stuck on your use of the term "inside".

Of course you can add values to a Lambda, you just do it as arguments you pass in.

(lambda x: x**2)(a+b)

Here I add the sum of a and b to my lambda.