I came across the sorted() example below and cannot figure out why lambda student: student[2] can represent a function specifying the integers in the tuple.
Can anyone lay out the mechanics or a clearer example of how python knows the lambda function student should pull data from student_tuples?
student_tuples = [
('john', 'A', 15),
('jane', 'B', 12),
('dave', 'B', 10)]
sorted(student_tuples, key=lambda student: student[2]) # sort by age
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
lambda student: student[2] is equivalent to the following function, aside from not having a name:
def <anonymous function>(student):
return student[2]
The reason why it winds up pulling from student_tuples is because the sorted() function passes each individual element from its first argument (the sequence to sort) to its key argument (a function that takes an element and returns the corresponding sort key). As such, sorted() passes each element of student_tuples to the lambda function in turn, during which the value of the element is temporarily assigned to the student variable.
lambda student: student[2]
clearer:
lambda x: x[2]
A lambda expression returns a function. The arguments for this function are before the ':' and separated by commas.
lambda x,y: x + y
The function does not have a name. But you can imagine as if lambda creates an abstract function. The lambda expression returns a function.
(Lambda is kind of essence of what a function is).
You can give lambda expressions also a name:
f = lambda x: x[2]
And now you can use the name to call the function.
f(["a", "b", "c"]) ## returns "c" because the list element "c" has index 2
list(map(f, student_tuples))
## [15, 12, 10]
or with the lambda expression:
list(map(lambda x: x[2], student_tuples))
## [15, 12, 10]
is actually what happens inside of sort:
the lambda-function is applied to each element of the list (map).
The outer list() around map() is necessary to execute map, because map is lazily evaluated (a promise to execute it but not yet executed).
Lazy evaluation is actually a nesting of lambdas ... well, lambdas are the core of functional programming. Programming languages like Lisp make you clear what lambda actually is. (You can also google for lambda calculus).
In R, a functional language, in such case the order of the iterable object indexes is determined and then applied on the object - for the ordering/sorting - to achieve the final sorted version (function sort)
I guess, sth similar is going on inside Python's sorted function.
Related
z = (lambda *a: a, (1,2))
print(z)
k = (lambda *a: a)(1,2)
print(k)
How does the comma (,) and parenthesis work here in lambda implementation?
Output:
(<function <lambda> at 0x000002648500E0D0>, (1, 2))
(1, 2)
If I remove the comma and give parenthesis I get the desired output (1,2).
However, if I give the comma it gives me function ... and (1,2).
Please make me understand.
First case;
z = (lambda *a: a, (1,2))
print(z)
Here z is a tuple which has two elements, lambda *a: a and another tuple (1, 2). When you print it, you will simply get these elements printed, ie, a function and a tuple;
(<function <lambda> at 0x000002648500E0D0>, (1, 2))
Another case;
k = (lambda *a: a)(1,2)
print(k)
Here you are creating a lambda function and to call the function, we add parenthesis at the end of the function and pass the parameters. That is what you are doing here.
By adding (1, 2) at the end of the lambda function calls it with 1 and 2 as parameters.
Also note that * before a in the lambda function (if you don't know). It means that spread the given list or tuple.
If I remove the comma... I get the desired output
So, your desired action is to invoke the lambda function
You don't execute functions using commas, in other words commas never exist between their names/definitions and their parameters, so if you'd expected that to work, it'd be a typo
Now, that all being said, your first line is functionally equivalent to
z=((lambda *a: a), (1,2), )
Which, hopefully makes it a little clearer that you've defined a tuple of two things, a function object and the tuple (1,2)
Regarding the output, as shown before, you're just printing a lambda - understanding the return type of anonymous function lambda
In the lambda ‘z’, because you don’t call the lambda you created (append a pair of parentheses and pass the parameters), so, it is just a lambda that returns a tuple which contains unpacked a and (1, 2).
In the lambda ‘k’, because you called the lambda you created, and you passed the parameter 1 and 2, so, according to the lambda, it returns an unpacked tuple (when 1 and 2 passed to the lambda, however, the parameter becomes (1, 2) ).
Because the lambda returns (1, 2), the variable ‘k’ was assigned with the returned value.
how to sort a list containing multiple datatypes in python 3.4?
for example:-
lixt=["Tak","jil","son",54,84]
lixt.sort()
Error:
TypeError: '<' not supported between instances of 'int' and 'str'
please help with the proper solution
use sorted(your_list, key=str) for simple cases when you can sort by the string representation of the item
l = ["Tak","jil","son",54,84]
sorted(l, key=str)
output: [54, 84, 'Tak', 'jil', 'son']
sorted takes three arguments: an iterable, a key and reverse i.e sorted(iterable, [key=None], [reverse=False]). The key argument allows you define a function which can be called to compare the values of items in the iterable. Some examples are given below:
# notice the function name is supplied without brackets
sorted(["Eva", "eva", "string", "Aaron"], key=str.lower)
# the same result using lambda
sorted(["Eva", "eva", "string", "Aaron"], key=lambda x: x.lower())
# comparing by the second element in a tuple: (name, age)
name_ages = [("Eva", 12), ("Tom", 14), ("Gerald", 4)]
# output is [('Gerald', 4), ('Eva', 12), ('Tom', 14)]
sorted(name_ages, key=lambda x: x[1])
Using lambdas or by defining functions of your own, the sorted function is very versatile.
NB: Use can also use the key argument in list.sort()
In the following Python script where "aDict" is a dictionary, what does "_: _[0]" do in the lambda function?
sorted(aDict.items(), key=lambda _: _[0])
Lets pick that apart.
1) Suppose you have a dict, di:
di={'one': 1, 'two': 2, 'three': 3}
2) Now suppose you want each of its key, value pairs:
>>> di.items()
[('three', 3), ('two', 2), ('one', 1)]
3) Now you want to sort them (since dicts are unordered):
>>> sorted(di.items())
[('one', 1), ('three', 3), ('two', 2)]
Notice that the tuples are sorted lexicographically -- by the text in the first element of the tuple. This is a equivalent to the t[0] of a series of tuples.
Suppose you wanted it sorted by the number instead. You would you use a key function:
>>> sorted(di.items(), key=lambda t: t[1])
[('one', 1), ('two', 2), ('three', 3)]
The statement you have sorted(aDict.items(), key=lambda _: _[0]) is just using _ as a variable name. It also does nothing, since aDict.items() produces tuples and if you did not use a key it sorts by the first element of the tuple anyway. The key function in your example is completely useless.
There might be a use case for the form (other than for tuples) to consider. If you had strings instead, then you would be sorting by the first character and ignoring the rest:
>>> li=['car','auto','aardvark', 'arizona']
>>> sorted(li, key=lambda c:c[0])
['auto', 'aardvark', 'arizona', 'car']
Vs:
>>> sorted(li)
['aardvark', 'arizona', 'auto', 'car']
I still would not use _ in the lambda however. The use of _ is for a throway variable that has minimal chance of side-effects. Python has namespaces that mostly makes that worry not a real worry.
Consider:
>>> c=22
>>> sorted(li, key=lambda c:c[0])
['auto', 'aardvark', 'arizona', 'car']
>>> c
22
The value of c is preserved because of the local namespace inside the lambda.
However (under Python 2.x but not Python 3.x) this can be a problem:
>>> c=22
>>> [c for c in '123']
['1', '2', '3']
>>> c
'3'
So the (light) convention became using _ for a variable either in the case of a list comprehension or a tuple expansion, etc where you worry less about trampling on one of your names. The message is: If it is named _, I don't really care about it except right here...
In Python _ (underscore) is a valid identifier and can be used as a variable name, e.g.
>>> _ = 10
>>> print(_)
10
It can therefore also be used as the name of an argument to a lambda expression - which is like an unnamed function.
In your example sorted() passes tuples produced by aDict.items() to its key function. The key function returns the first element of that tuple which sorted() then uses as the key, i.e that value to be compared with other values to determine the order.
Note that, in this case, the same result can be produced without a key function because tuples are naturally sorted according to the first element, then the second element, etc. So
sorted(aDict.items())
will produce the same result. Because dictionaries can not contain duplicate keys, the first element of each tuple is unique, so the second element is never considered when sorting.
In Python, lambda is used to create an anonymous function. The first underscore in your example is simply the argument to the lambda function. After the colon (i.e. function signature), the _[0] retrieves the first element of the variable _.
Admittedly, this can be confusing; the lambda component of your example could be re-written as lambda x: x[0] with the same result. Conventionally, though, underscore variable names in Python are used for "throwaway variables". In this case, it implies that the only thing we care about in each dictionary item is the key. Nuanced to a fault, perhaps.
I have an interview recently. The interviewer asked me the ways to iterate dict in python. I said all the ways use for statement. But he told me that how about lambda?
I feel confused very much and I consider lambda as an anonymity function, but how it iterates a dict? some code like this:
new_dict = sorted(old_dict.items(), lambda x: x[1]) # sorted by value in dict
But in this code, the lambda is used as a function to provide the compared key. What do you think this question?
You don't iterate with lambda. There are following ways to iterate an iterable object in Python:
for statement (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, itertools module)
Manually call next function until StopIteration happens.
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())
Using a plain lambda to iterate anything in Python sounds very wrong. Certainly the most Pythonic method to iterate sequences and collections is to use list comprehensions and generator expressions like #Andrey presented.
If the interviewer was leaning on the more theoretical/Computer Sciencey answers, it is worth noting that using lambdas to iterate is quite possible, although I must stress that this is not Pythonic nor useful at any context other than academic exercises:
# the legendary Y combinator makes it possible
# to let nameless functions recurse using an indirection
Y = lambda f: (lambda x: x(x))(lambda y: f(lambda *args: y(y)(*args)))
# our iterator lambda
it = lambda f: lambda Lst: (Lst[0], f(Lst[1:])) if Lst else None
# see it in action:
Y(it)([1,2,3])
=> (1, (2, (3, None)))
lambda itself doesn't iterate anything. As you thought, it just defines an anonymous function - aside from the syntactic rule about only being able to have an expression, a lambda does nothing more than a similar function made using def. The code inside the lambda might iterate something, but only in the same ways as any other function might use (provided they are expressions, and so valid inside a lambda).
In the example you mention using sorted, the key function is called on each element of the list being sorted - but it is sorted itself that does this, and which does the iteration. When you provide a key function, sorted does something broadly similar to this:
def sorted(seq, key):
decorated = [(key(elem), i) for i, elem in enumerate(seq)]
# Sort using the normal tuple lexicographic comparisons
decorated.sort()
return [seq[i] for _,i in decorated]
As you can see, sorted does the iteration here, not the lambda. Indeed, there is no reason why the key has to be a lambda - any function (or any callable) will do as far as sorted is concerned.
At the lowest level, there is only really one way to iterate a dict (or, indeed, any other iterable) in Python, which is to use the iterator protocol. This is what the for loop does behind the scenes, and you could also use a while statement like this:
it = iter(my_iterable)
while True:
try:
val = next(it)
except StopIteration:
# Run else clause of for loop
break
else:
# Run for loop body
The comments in this aren't strictly part of the iterator protocol, they are instead part of the for loop (but having at least a loop body in there is mostly the point of iterating in the first place).
Other functions and syntax that consume iterables (such as list, set and dict comprehensions, generator expressions or builtins like sum, sorted or max) all use this protocol, by either:
Using a Python for loop,
Doing something like the above while loop (especially for modules written in C),
Delegating to another function or piece of syntax that uses one of these
A class can be made so that its instances become iterable in either of two ways:
Provide the iterator protocol directly. You need a method called __iter__ (called by iter), which returns an iterator. That iterator has a method called __next__ (just next in Python 2) which is called by next and returns the value at the iterator's current location and advances it (or raises StopIteration if it is already at the end); or
Implement part of the sequence protocol (which means behaving like a list or tuple). For forward iteration, it is sufficient to define __getitem__ in such a way that doing my_sequence[0], my_sequence[1], up until my_sequence[n-1] (where n is the number of items in the sequence), and higher indexes raise an error. You usually want to define __len__ as well, which is used when you do len(my_sequence).
Dictionary iteration using lambda
dct = {1: '1', 2 : '2'}
Iterating over Dictionary using lambda:
map(lambda x : str(x[0]) + x[1], dct.iteritems())
here x[0] is the key
and x[1] is the value
Result :
['11', '22']
Filtering on Dictionary using lambda:
filter(lambda x : x[0] > 1, dct.iteritems())
Result :
[(2, '2')]
The best way to iterate dict in python is:
dic ={}
iter_dic = dic.iteritems().next
iter_dic()
...
iter_dic()
But you can build it with lambda func:
iter_dic = lambda dic: dic.keys()[0],dic.pop(dic.keys()[0])
iter_dic(dic)
...
iter_dic(dic)
Could we say
count = {8: 'u', 4: 't', 9: 'z', 10: 'j', 5: 'k', 3: 's'}
count_updated = dict(filter(lambda val: val[0] % 3 == 0,
count.items()))
is iterating Dictionary with Lambda function?
It will produce:
{8: 'u', 4: 't', 9: 'z', 10: 'j', 5: 'k', 3: 's'}
{9: 'z', 3: 's'}
from Python dictionary filter + Examples.
I have a dictionary like the following. Key value pairs or username:name
d = {"user2":"Tom Cruise", "user1": "Tom Cruise"}
My problem is that i need to sort these by the Name, but if multiple users contain the same name like above, i then need to sort those by their username. I looked up the sorted function but i dont really understand the cmp parameter and the lambda. If someone could explain those and help me with this that would be great! Thanks :)
cmp is obsolescent. lambda just makes a function.
sorted(d.iteritems(), key=operator.itemgetter(1, 0))
I'm just going to elaborate on Ignacio Vazquez-Abrams's answer. cmp is deprecated. Don't use it. Use the key attribute instead.
lambda makes a function. It's an expression and so can go places that a normal def statement can't but it's body is limited to a single expression.
my_func = lambda x: x + 1
This defines a function that takes a single argument, x and returns x + 1. lambda x, y=1: x + y defines a function that takes an x argument, an optional y argument with a default value of 1 and returns x + y. As you can see, it's really just like a def statement except that it's an expression and limited to a single expression for the body.
The purpose of the key attribute is that sorted will call it for each element of the sequence to be sorted and use the value that it returns for comparison.
list_ = ['a', 'b', 'c']
sorted(list_, key=lambda x: 1)
Just read the rest for a hypothetical example. I didn't look at problem closely enough before writing this. It will still be educational though so I'll leave it up.
We can't really say much more because
You can't sort dicts. Do you have a list of dictss? We could sort that.
You haven't shown a username key.
I'll assume that it's something like
users = [{'name': 'Tom Cruise', 'username': user234234234, 'reputation': 1},
{'name': 'Aaron Sterling', 'username': 'aaronasterling', 'reputation': 11725}]
If you wanted to confirm that I'm more awesome than Tom Cruise, you could do:
sorted(users, key=lambda x: x['reputation'])
This just passes a function that returns the 'reputation' value for each dictionary in the list. But lambdas can be slower. Most of the time operator.itemgetter is what you want.
operator.itemgetter takes a series of keys and returns a function that takes an object and returns a tuple of the value of its argument.
so f = operator.itemgetter('name', 'username') will return essentially the same function as
lambda d: (d['name'], d['username']) The difference is that it should, in principle run much faster and you don't have to look at ugly lambda expressions.
So to sort a list of dicts by name and then username, just do
sorted(list_of_dicts, operator.itemgetter('name', 'username'))
which is exactly what Ignacio Vazquez-Abrams suggested.
You should know that dict can't be sorted. But python 2.7 & 3.1 have this class collections.OrderedDict.
So,
>>> from collections import OrderedDict
>>> d=OrderedDict({'D':'X','B':'Z','C':'X','A':'Y'})
>>> d
OrderedDict([('A', 'Y'), ('C', 'X'), ('B', 'Z'), ('D', 'X')])
>>> OrderedDict(sorted((d.items()), key=lambda t:(t[1],t[0])))
OrderedDict([('C', 'X'), ('D', 'X'), ('A', 'Y'), ('B', 'Z')])