5 ms·
Question about this part: key = operator.itemgetter("name") people = sorted([p1, p2, p3], key=key) What's the advantage of using operator module inste
by thrdbndndn 4y ago
Question about this part:
key = operator.itemgetter("name")
people = sorted([p1, p2, p3], key=key)
What's the advantage of using operator module instead of just
key=lambda x: x['name']
?
- kzrdude 4y agoIt's faster (better performance). It could also be preferred just as a coding style.
- kzrdude 4y agoThis makes me wonder, couldn't python have a peephole optimization that replaces certain easy labmdas like this with operator functions? Maybe it's too noticeable to work as a transparent optimization (function kind and name etc changes).
- winstonewert 4y agoSuch optimizations can't be transparent in python (at least not easily) because you could very well reassigned everything in `operator` to do whatever you want. PyPy can do it with its jit because it supports invalidating compiled code when such changes are made.
- eesmith 4y agoAssuming the implementation has access to the "real" operator.itemgetter, I can't think of a case where lambda x: x['name'] cannot be replaced by a operator.itemgetter("name") and get a different result. ... except for the stack trace: >>> f = lambda x: x["A"] >>> f({"A": 3}) 3 >>> f({"B": 3}) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 1, in <lambda> KeyError: 'A' >>> import operator >>> f = operator.itemgetter("A") >>> f({"A": 3}) 3 >>> f({"B": 3}) Traceback (most recent call last): File "<stdin>", line 1, in <module> KeyError: 'A' So if 'x' implemented its own getitem and it inspected the stack (eg, how Pandas uses the 'level' parameter in 'eval' and 'query' methods to get locals() and globals()), then this change would cause different results.
- winstonewert 4y agoOh, I see. I think you are right.
- deleted 4y ago[deleted]
- tonyg 4y agoHoly shit, you're right. It's about 33% faster on Python 3.10 on my machine: import operator n1 = operator.itemgetter('name') n2 = lambda x: x['name'] x = {'name': 'abcdef'} import timeit print(timeit.timeit('n1(x)', globals=globals())) print(timeit.timeit('n2(x)', globals=globals())) I'm so surprised because I went and read (what I thought was) the source for operator.itemgetter, which boils down to a wrapper object around the plain version. It turns out that this is not the source code. As with so many other things in Python, there's a special case you have to know about: there's a separate C implementation of the operator module. :-/
- ssl232 4y ago> It turns out that this is not the source code. As with so many other things in Python, there's a special case you have to know about: there's a separate C implementation of the operator module. :-/ I actually kinda like that Python often maintains 100% compatible pure-Python implementations of various C modules. It's definitely niche, but I have sometimes found myself trying to work out what a module is doing (e.g. with the fancy new PEG parser) and I find it far easier to read Python than C.
- kzrdude 4y agoI'd expect it to be even better improvement inside sort, but maybe my hunch is wrong. The significance is greater there, at least.
- ehsankia 4y agoI generally agree that it's not worth importing operator just to get access to itemgetter. operator module has a few other nice functions though.
- kzrdude 4y agoWhat's your favourite operator feature?
- Etherlord87 4y agoI'm not the same person, but there's not much in operator module that can't be done by simply using an operator symbol. It's useful to use in e.g. map(), but you could use lambdas instead (for some performance overhead as mentioned). operator.countOf() is perhaps the hardest to reimplement in lambda, as it's more reliable than lambda x: x.count() - for example it will work for dictionary.values() as well.
- _ZeD_ 4y agoFWIW I prefer itemgetter to a lambda