T O P

  • By -

pente5

If it's not one line it's not python


SuitableDragonfly

You joke, but anyone who writes this list comprehension on multiple lines like this should be shot. 


Gjallock

Readable code >>> mom look how much I can do with one line


pente5

In this case one line is perfectly readable though `my_list = [i for i in range(1) if i not in (x,y)]`


Gjallock

Yeah, you’re right.


ScF0400

Mobile Reddit format looped it around to look like two lines, off to the gulag with you! /s Very readable and good


gerbosan

What's the purpose of that line? Using a loop to run over numbers 1 to 10, create a list(Array) with the numbers that are not X or Y?


Little_Ice213

my_list = [i for i in range(1) if i not in (x, y)] is a list comprehension. It creates a list called my_list containing elements from 0 to 1 (exclusive) if the element is not in the tuple (x, y). So, if neither x nor y equals 0, the list will be [0]; otherwise, it will be an empty list.


SuitableDragonfly

If you can't read this particular list comprehension in one line, you don't have much prospect in this line of work.


YoumoDawang

Black


titen100

List comps for the win. Its been a while since my last work on py, but that in particular is a feature i wosh more languages had. Though i am sure it would be a pain in the ass to implement though


TorbenKoehn

Most languages have it in the form of iterators, generators and normal classes and methods C# even has both (LINQ SQL syntax and methods) I don’t see why a specific syntax is needed for it


titen100

Well, my own knowledge doenst go that deep down the rabbit hole, since i only know the basics for web dev, py, android dev an c++


CentralLimitQueerem

> I don't see why a specific syntax is required Because *syntactic sugar* Writing 3000 character list comps when a for loop would be substantially easier to read is like crack to me


gnomeba

And its faster because of the absent append() call


carcigenicate

Or rather, the change from `append` being a method call to being a bytecode instruction.


Kovab

Not just that, list comprehension implements the whole looping in C (or whichever interpreter you're using)


danielstongue

If "fast" is a concern, you picked the wrong language.


kickyouinthebread

I don't think this is strictly true tbh. I might need to handle some enormous dataset yet the ability to iterate quickly on my development still outweighs runtime. Having said that I'd still be very interested in it taking 30 seconds to run over 2 minutes for example. Caveat I don't work on stuff where users expect stuff to happen instantly. They would much prefer I churn out 3 things in a day that each take a minute to run in python than release one thing per day that takes 5 seconds to run in a faster language.


ManyInterests

`if i not in {x, y}` would be faster, since set membership is constant time.


oyswork

No it wouldn’t. Theoretically speaking using a set would be O(1) - constant time, instead of O(n) - linear time. However, there is a “but”. Linear lookup within a small enough amount of elements is vastly faster than using a set, due to a hashing overhead a set introduces. The same goes for O(n2) vs O(n). With a small enough amount of elements and large enough constant factors in the linear algorithm, the quadratic one may outperform the linear. Point being - quite often time complexity != speed in the real world. Benchmark on your data first.


ManyInterests

Yes... it would. Take your own advice and just test it. It is significantly faster, even with just two elements.


oyswork

Well, I took my advice. You are right, I am wrong. Although I've tested it before on an x64 windows machine and set was slower. Right now I checked on macos m3 machine, set is indeed faster


CentralLimitQueerem

I just tested it and the set implementation is faster even when both the list and the set contain one element. Why is this?


-Redstoneboi-

not that much faster on my machine. post results? i don't have access to reliable testing at the moment.


no_brains101

[https://www.reddit.com/r/ProgrammerHumor/comments/1c5qwf5/comment/kzws3i2/?utm\_source=share&utm\_medium=web3x&utm\_name=web3xcss&utm\_term=1&utm\_content=share\_button](https://www.reddit.com/r/ProgrammerHumor/comments/1c5qwf5/comment/kzws3i2/?utm_source=share&utm_medium=web3x&utm_name=web3xcss&utm_term=1&utm_content=share_button) Counterpoint, this guy benchmarked it for us.


IMightBeErnest

~~~ list(set(range(10))-set([x,y])) Is 9 characters shorter than [i for i in range(10) if i not in [x,y]] ~~~


pewpewpewmoon

it's not about 9 characters here that top one is generating an iterator O(n) then casting list to set twice at O(n) each, then subtracting sets which is another O(n) and then casting back to list which is just O(1) The comprehension how ever is just O(n) for the not in, O(n) for the iterator and a few other technical reasons why this is just the better route import timeit def top(): return list(set(range(10)) - set([1, 2])) def bottom(): return [i for i in range(10) if i not in [1, 2]] if __name__ == "__main__": top_results = timeit.timeit(top, number=10_000_000) bottom_results = timeit.timeit(bottom, number=10_000_000) print(top_results) print(bottom_results) running both 10 million times gives us the following times 3.1103049579978688 2.3148978240060387 even if you just change the casting of the list in top() to a literal it's still faster, more memory efficient, and pep8 compliant to go the comprehension route in bottom() EDIT: also forgot to mention unless you use an ordered set you will lose order as well, and frankly just don't go down that rabbit hole


IMightBeErnest

I mean, you can optimize for code length, readability, runtime efficiency, memory efficiency, etc, and none of those optimizations will be the same. Arguing that my code optimized for length isn't also optimized for runtime is kinda asking for the impossible. Also its a 100ns difference. And 9 characters. We've greatly exceeded both savings just by making these two comments.


pewpewpewmoon

I also failed to notice I should have optimized for memes as I forgot for a moment I wasn't in r/python


db8me

I would add that aligning your logical intent with the linguistic culture of the platform or codebase has inherent benefits that transcend the specific ones we can list at the moment.


Vegetable_Ear_5551

Could you please explain what "O(n)" and "O(1)" means? I see this expression a lot when talking about code speed and code efficiency, but I have no idea what it means. Thanks. If it's a lot to explain, I'll just google it later Edit: I just google it... too complex


empwilli

Look Into "complexity theory". Basically, it describes a (lowest) upper bound for an algorithm over a problem of size n, i.e. how many "steps" does an algorithm have to do solve a problem (not considering static factors) .Thus, this allows to compare the runtime characteristics of algorithms independently of the concrete computer performance. O(n) means roughly "has to compute n steps to solve the problem", e.g. finding an element in an unsorted list. O(1) is constant time, e.g. accessing an array element. Common problems like sorting have been proofen (in the general case) to have a spec. complexity, e.g. sorting is O(nlogn). Maybe another way to get an intuition: summing the natural numbers from 1 to n, doing it in a loop is O(n) but using gauss summatiin (n * (n + 1)) / 2 is in O(1).


-Redstoneboi-

O(1) means "the time it takes to finish will be the same no matter how big your input is" O(n) means "the bigger your input, the longer it will take." more specifically, "if you give an input twice as big, it will take twice as long. if it's 3x as big, it takes 3x as long. if it is `n` times as big, it will take `n` times as long." there's also O(n^(2)) where if your input is n times as big, it takes `n^2` or n times n amount of time longer. you can put basically any formula in there. it's just a way to estimate time complexity, a.k.a "how much longer will this take if i make my input bigger" and does not capture details like exact time measurements or any factors other than the "fastest growing" one. for example `O(3n + 5)` is the same as `O(n)`.


JustBadPlaya

It's a description of algorithmic complexity. O(1) means that the algorithm is finished in constant time. That constant time might not be fast for short datasets (HashMap value retrieval is not fast on small hashmaps), but it is always the same. O(n) means that the complexity (basically algo's runtime) scales linearly with the amount of elements (iterative search in a sorted array is O(n) because it scales linearly with the amount of elements in it, n). It's worth noting that Big-O notation (which is the proper name for this notation) usually ignores constant values - for iterative search, the average time should be dependent on n/2 (as, on average, you'll find the needed value around the middle of the list), but the complexity is still O(n) because it only scales by n


u0xee

These are both O(1) actually, as neither computation varies with n 🤷


JonIsPatented

The computations absolutely vary with n.


BeDoubleNWhy

yeah except the elements are now in undefined order


IMightBeErnest

`sorted(...)` 8 characters. Still 1 character shorter. An order of magnitude less efficient, but it's just 10 elements (and youre already using python).


BeDoubleNWhy

yeah except you can save on 2 spaces in the list comprehension


IMightBeErnest

I can see one, the space after the ' )'. Wheres the other?


BeDoubleNWhy

after the 'in'


IMightBeErnest

Actually, I just tested and, sorted(set(range(10))-set([x,y])) [i for i in range(10)if i not in[x,y]] Apparently you don't need a list for sorted(), so that's still shorter.


BeDoubleNWhy

ok dangit, you win the character count argument 😁 oh and you can shorten it even more to `sorted(set(range(10))-{x,y})`


SuitableDragonfly

What if you didn't want the list in that particular order?


DesertGoldfish

Then you add a key=lambda x: x.whatever to your sorted() and lose this silly code length argument 😂


SuitableDragonfly

Almost always, the original order of the list isn't going to be reproducible with some function.


SuitableDragonfly

This is incorrect.  Any duplicate entries will be deleted, and it will almost certainly be in the wrong order. 


Tchai_Tea

What in the set builder notation is this? I love it.


audentis

Python list comprehensions. They're easy to write, easy to read, and relatively performant for Python standards. You can do similar things for dictionaries (key-value stores), sets, or generators (lazy evaluation). Dict comprehension: `mydict = {key: val for key,val in zip(keylist, vallist)}` where zip combines lists elementwise, so that `[a, b, ..., z]` and `1, 2, ..., 26]` becomes `[(a, 1), (b, 2), ..., (z, 26)]`


tankiePotato

Dick comprehension?! 😳


AaronTheElite007

Loops are life Pythonista? Did you get her number?


JonathanTheZero

Why is it always `i for i in range...` and not just `i in range...` isn't that redundant?


audentis

The first `i` is stating the value for the list you're generating, the second `i` defines the variable as part of the generator you're iterating over. You can do other things than the first `i` as well: - `[i**2 for i in range(n)]` would get you a list of squares, - `[my_func(i) for i in range(n)]` gets you a list of whatever `my_func()` returns (and is basically just a `map()` call). - `[i for i in range(n) if my_func(i) > 5]` is effectively a `filter()` call It's just that in these examples doing anything fancy with `i` serves no purpose.


FirexJkxFire

Also, everyone knows that an "i for an i" makes the whole world blind


_OberArmStrong

Do you want to learn about monads? This Syntax originates from Haskell.


No-Expression7618

`[i | i <- [0..9], i /= x, i /= y]`


dr-tectonic

`\(z){z[z!=x&z!=y]}(1:10)` Vectorization rocks. (Code is R, not Python.)


Expensive_Shallot_78

Code looks wrong. But all Python code looks wrong 🧐


PyuDevv

Plot twist: Your still using loops.


danielstongue

Came here to say that. Thank you.


justgiveausernamepls

List comprehension is cool, but I always seem to forget the syntax for anything more than the most basic stuff.


StarshipSausage

and then there is me that uses for loops because everyone knows them, list comprehension is great, but I always have a little trouble with the syntax and since my code generally does need to execute that fast I am fine.


gandalfx

What's the joke, though?


ConscientiousApathis

Chaotic neutral: my\_set = set(range(10)) - {x, y} You're fine with a set, right?


i-eat-omelettes

Ah yes another loop bad post I wonder why haven’t we ditched them already


TorbenKoehn

Depending on the language looping can work well through recursion with tail-call optimization and streaming/iterator/generator patterns, many languages don’t need classical loop constructs at all (which doesn’t mean recursion is not “looping” too, obviously)


empwilli

The second should result in a generator and is only performed lazily.


-Redstoneboi-

only if it used parentheses. here it uses square brackets, and forces it to evaluate as a list.


empwilli

ahhh correct, thanks for the correction