4 ms·
I love the functional aspects of Python. It's nice to break the monotony of loops every once and while.
by StClaire 10y ago
I love the functional aspects of Python. It's nice to break the monotony of loops every once and while.
- Alex3917 10y agoI dunno. I love the functional parts of Groovy. But with Python I generally only break out the functional stuff when it's a choice between one unreadable line of code with a comment or else six unreadable lines of code. (E.g. when parsing an API response with weird and arbitrary nesting.)
- foota 10y agoWhich is supposed to be functional in that example?
- Alex3917 10y agoThe one line would be functional. Here is a good example: list(filter(lambda x : ('widgets' in x), mixed_widgets))[0]['widgets'] I almost always go for more lines of readable code rather than less lines of unreadable code. But in cases like this, you can either write that as one line of garbage unreadable code or six lines of garbage unreadable code. So I'd rather just leave the overall codebase more dense to make it easier to understand the program flow, and then leave a comment explaining what that line is doing.
- deleted 10y ago[deleted]
- aftbit 10y agoYou could also use the list comprehension form of that: [x for x in mixed_widgets if 'widgets' in x][0]['widgets'] More readable? I dunno. More "Pythonic"? Definitely. Related: I wish the list type in Python included an analogue to dict's ".get(key, default)" operation.
- m_mueller 10y agodefinitely more readable - it describes in basic english words what it's doing and it's basically the same as mathematical set notation. The main question to me is the performance implication though. Are generator expressions doing the iteration at C level like map and does that give performance parity then? What about branching - am I correctly assuming that filter is always faster than comprehensions or generator expressions with if-parts?
- clusmore 10y agoMust watch: https://www.youtube.com/watch?v=OSGv2VnC0go https://www.youtube.com/watch?v=OSGv2VnC0go I believe that the list comprehension will be faster than filter, but as always, any time you replace readable code with unreadable code for performance reasons, you damn well better time it.
- m_mueller 10y agoThat's actually the talk I was thinking about, but I guess I forgot how exactly Raymond described generator expressions there. Thanks for linking it again!
- viraptor 10y ago~4.5 times faster with comprehension. In [11]: timeit.timeit('''list(filter(lambda x : ('widgets' in x), mixed_widgets))[0]['widgets']''', '''nw={'abc': 'def'};w={'widgets':'s'};mixed_widgets=[nw]*100+[w]+[nw]*100''', number=100000) Out[11]: 2.6956532129988773 In [12]: timeit.timeit('''[x for x in mixed_widgets if 'widgets' in x][0]['widgets']''', '''nw={'abc': 'def'};w={'widgets':'s'};mixed_widgets=[nw]*100+[w]+[nw]*100''', number=100000) Out[12]: 0.5911771030077944 But not generating the list at all is still going to be faster (with bigger gains for bigger data) In [13]: timeit.timeit('''next(x for x in mixed_widgets if 'widgets' in x)['widgets']''', '''nw={'abc': 'def'};w={'widgets':'s'};mixed_widgets=[nw]*100+[w]+[nw]*100''', number=100000) Out[13]: 0.3324074839911191
- 10y ago
- ebola1717 10y agoarghhh that's mostly unreadable because it's out of order. in ruby it's perfectly readable: mixed_widgets.filter { |x| x.contains('widgets') }[0]['widgets']
- deleted 10y ago[deleted]
- tommikaikkonen 10y agoImplementing a find function makes this read a lot nicer. You could also call it find_first or find_next. def find(predicate, iterable, default=None): """Returns the first value that matches predicate, otherwise default=None""" return next( (x for x in iterable if predicate(x)), default ) Which turns the expression to find(lambda x: 'widgets' in x, mixed_widgets)['widgets']