You cannot use assignments in a expression, and a lambda only takes an expression.
You can store lambdas in dictionaries just fine otherwise:
dict = {'Applied_poison_rating_bonus' : (lambda target, magnitude: target.equipmentPoisonRatingBonus + magnitude)}
The above lambda of course only returns the result, it won't alter target.equimentPoisonRatingBonus in-place.
Lambda function dictionary update - Ideas - Discussions on Python.org
dictionary - lambda in python can iterate dict? - Stack Overflow
python: dict of (lambda) functions - Stack Overflow
dictionary - Lambda function in Python using dictionaries - Stack Overflow
Videos
''' Here's the dictionary for a program I'm building. I'm getting a TypeError
saying int object is not callable when I try to run the second print function, \
but the first one works fine. What's the difference between the two and is there
a way for this to work without a problem?'''
formulas = {1: lambda x: x(x+1)/2,
2: lambda x: x**2,
3: lambda x: x(3 * x - 1)/2,
4: lambda x: x(2 * x - 1),
5: lambda x: x(5 * x - 3)/2,
6: lambda x: x(3 * x - 2)
}
print(formulas[2](4))
print(formulas[4](4))You don't iterate with lambda. There are following ways to iterate an iterable object in Python:
forstatement (your answer)- Comprehension, including list
[x for x in y], dictionary{key: value for key, value in x}and set{x for x in y} - Generator expression:
(x for x in y) - Pass to function that will iterate it (
map,all,itertoolsmodule) - Manually call
nextfunction untilStopIterationhappens.
Note: 3 will not iterate it unless you iterate over that generator later. In case of 4 it depends on function.
For iterating specific collections like dict or list there can be more techniques like while col: remove element or with index slicing tricks.
Now lambda comes into the picture. You can use lambdas in some of those functions, for example: map(lambda x: x*2, [1, 2, 3]). But lambda here has nothing to do with iteration process itself, you can pass a regular function map(func, [1, 2, 3]).
You can iterate dict using lambda like this:
d = {'a': 1, 'b': 2}
values = map(lambda key: d[key], d.keys())
The fix:
def make_closure(number):
return lambda x: myfct(x, number)
used as
{'add_{}'.format(number): make_closure(number) for number in range(10)}
The reason for this behaviour is, that the variable number (think: named memory location here) is the same during all iterations of the loop (though its actual value changes in each iteration). "Loop" here refers to the dictionary comprehension, which internally is based on a loop. All lambda instances created in the loop will close over the same "location", which retains the value last assigned to it (in the last iteration of the loop).
The following code is not what actually happens underneath. It is merely provided to shed light on the concepts:
# Think of a closure variable (like number) as being an instance
# of the following class
class Cell:
def __init__(self, init=None):
self.value = None
# Pretend, the compiler "desugars" the dictionary comprehension into
# something like this:
hidden_result_dict = {}
hidden_cell_number = Cell()
for number in range(10):
hidden_cell_number.value = number
hidden_result_dictionary['add_{}'.format(number)] = create_lambda_closure(hidden_cell_number)
All lambda closures created by the create_lambda_closure operation share the very same Cell instance and will grab the value attribute at run-time (i.e., when the closure is actually called). By that time, value will refer to last value ever assigned to it.
The value of hidden_result_dict is then answered as the result of the dict comprehension. (Again: this is only meant as be read on a "conceptual" level; it has no relation to the actual code executed by the Python VM).
number is a variable which has different value for each iteration of the dict comprehension. But when you do lambda x: myfct(x, number), it does not use value of number. It just creates a lambda method that will use value of number when it will be called/used. So when you use you add_{} methods, number has value 9 which is used in every call to myfct(x, number).
The reason it doesn't work has to do with late-binding closures in Python.
Python’s closures are late binding. This means that the values of variables used in closures are looked up at the time the inner function is called.
Adapting the source explanation, whenever the return function is called, the value of key is looked up in the surrounding scope at call time. By then, the loop has completed and key is left with its final value of 'foo'.
You can resolve this by creating a closure that binds immediately to its arguments by using a default arg like so:
a = {'bar': 0, 'foo': 1} # a reference dictionary
dic1 = {'bar': lambda x: x['bar'], 'foo': lambda x: x['foo']}
dic2 = {key: lambda x, key=key: x[key] for key in a}
print(dic1'bar', dic1'foo')
print(dic2'bar', dic2'foo')
Result:
0 1
0 1
One simple way to do that is with operator.itemgetter:
from operator import itemgetter
a = {'bar': 0, 'foo': 1}
dic1 = {key: itemgetter(key) for key in a}
print(dic1'bar', dic1'foo')
# 0 1
Alternatively, you need to bind each value of key to each dictionary value, typically you do that with something like this:
a = {'bar': 0, 'foo': 1}
dic1 = {key: (lambda key: lambda x: x[key])(key) for key in a}
print(dic1'bar', dic1'foo')
# 0 1