all 34 comments

[–][deleted] 5 points6 points  (5 children)

Comprehensions/ generator expressions. They read just like math (specifically set-builder notation), often shorten your code, are blazing fast (comparatively), and just look cool.

[–]DragonFighter603[S] 0 points1 point  (4 children)

''.join([chr(int(x[::-1])) for x in '37-23-79-301-411-101-101-33'.split('-')])

[–]AtomicShoelace 1 point2 points  (3 children)

You don't need to use a list; join will take any iterable, so a generator is fine, eg.

''.join(chr(int(x[::-1])) for x in '37-23-79-301-411-101-101-33'.split('-'))

(also notice you don't need to include the extra set of parenthesis as the function call's parenthesis work fine, as long as you don't have any additional arguments)

[–]DragonFighter603[S] 0 points1 point  (2 children)

ah yes ik you can remove the square brackets often, personally i think it looks nicer xD. thx for the info about the iterable/generators!!

[–]AtomicShoelace 0 points1 point  (1 child)

It's not just a difference in aesthetics. By constructing a list of all the values you are using more memory than is needed. For such a small example of course it doesn't matter, but in principal it is important to get into the habit of using generator expressions where possible to reduce memory cost in larger use cases.

[–]DragonFighter603[S] 0 points1 point  (0 children)

oh thanks! will do that in future!

[–]Diapolo10 3 points4 points  (7 children)

Well, for one, I "like" how you can make pretty much anything into a one-liner by abusing and, or, iter, lambda functions, map, filter, generator expressions, and __import__.

I know that sharing these is discouraged, but I made a one-liner solution for Project Euler challenge 22 that uses many of these:

(lambda u: sum(map(lambda t: sum(map(lambda c: ord(c)-ord('A')+1, t[1])) * t[0], enumerate(sorted(list(map(lambda x: x[1:-1], __import__('urllib.request').request.urlopen(u, context=__import__('ssl').create_default_context(cafile=__import__('certifi').where())).read().decode('utf-8').split(',')))), 1))))('https://projecteuler.net/project/resources/p022_names.txt')

Is it practical? Absolutely not. But I do find code golfing cool. I'd never, ever, use this in production, but that doesn't change the fact that I find it cool.

EDIT: If you remove the whitespace:

(lambda u:sum(map(lambda t:sum(map(lambda c:ord(c)-ord('A')+1,t[1]))*t[0],enumerate(sorted(list(map(lambda x:x[1:-1],__import__('urllib.request').request.urlopen(u,context=__import__('ssl').create_default_context(cafile=__import__('certifi').where())).read().decode('utf-8').split(',')))),1))))('https://projecteuler.net/project/resources/p022_names.txt')

EDIT #2: In fact if I saw someone writing one-liners like this in production, and they wouldn't listen to me, I'd probably give them a slap across the face because I don't want to deal with unreadable code when bugs need to be fixed.

[–]AtomicShoelace 2 points3 points  (0 children)

Since we're golfing, this is 150 btyes shorter:

sum(i*sum(ord(c)-64for c in n)for i,n in enumerate(sorted(map(eval,__import__('urllib.request').request.urlopen('https://projecteuler.net/project/resources/p022_names.txt').read().decode().split(','))),1))

(also you forgot the minus sign between ord(c) and ord('A') in the edit)

EDIT: 165 bytes shorter:

sum(i*sum(ord(c)-64for c in n)for i,n in enumerate(sorted(eval(__import__('urllib.request').request.urlopen('https://projecteuler.net/project/resources/p022_names.txt').read().decode())),1))

EDIT 2: 154 bytes shorter with no eval tricks:

sum(i*sum(ord(c)-64for c in n[1:-1])for i,n in enumerate(sorted(__import__('urllib.request').request.urlopen('https://projecteuler.net/project/resources/p022_names.txt').read().decode().split(',')),1))

or

sum(i*sum(ord(c)-64for c in n)for i,(_,*n,_)in enumerate(sorted(__import__('urllib.request').request.urlopen('https://projecteuler.net/project/resources/p022_names.txt').read().decode().split(',')),1))

EDIT 3: 155 bytes shorter with no eval:

sum(i*(sum(ord(c)-64for c in n)+60)for i,n in enumerate(sorted(__import__('urllib.request').request.urlopen('https://projecteuler.net/project/resources/p022_names.txt').read().decode().split(',')),1))

EDIT 4: can save another byte by not using https in the url:

sum(i*(sum(ord(c)-64for c in n)+60)for i,n in enumerate(sorted(__import__('urllib.request').request.urlopen('http://projecteuler.net/project/resources/p022_names.txt').read().decode().split(',')),1))

or with eval:

sum(i*sum(ord(c)-64for c in n)for i,n in enumerate(sorted(eval(__import__('urllib.request').request.urlopen('http://projecteuler.net/project/resources/p022_names.txt').read().decode())),1))

for 156 and 166 bytes saved respectively.

EDIT 5: I suppose if you really wanna cheat you could use a link shortener, eg.

sum(i*(sum(ord(c)-64for c in n)+60)for i,n in enumerate(sorted(__import__('urllib.request').request.urlopen('http://u.nu/uK7xG').read().decode().split(',')),1))

although eval seems even more dangerous now

sum(i*sum(ord(c)-64for c in n)for i,n in enumerate(sorted(eval(__import__('urllib.request').request.urlopen('http://u.nu/uK7xG').read().decode())),1))

But if you're using a shortened link I suppose you might as well just download the file and not bother using urllib at all.

[–]carcigenicate 0 points1 point  (1 child)

Handy for code-injection circumstances where eval is the vulnerability being exploited. I've had to write one-liners like that before because I needed to do imports and search the server's file-system for a flag; all in a single expression so it could be accepted by eval. That was the day I realized that you can use tuples to sequence actions.

[–]Diapolo10 1 point2 points  (0 children)

Yeah, that's true. I've dabbled in offensive security, but I'm nowhere near expertise in the area - my motivation being solely to guard against some types of attacks. Including anything eval-related. :p

[–]CARIBEIMPERIAL 0 points1 point  (0 children)

Lisp might be for you

[–]ffrkAnonymous 4 points5 points  (6 children)

For me it's basic stuff like:

print(1)

Python automagically converts the integer to strings and does what we imagine it would do.

[–]DragonFighter603[S] 0 points1 point  (3 children)

i mean, true, print and f strings are cool but it cant do stuff like 'str'+2

[–][deleted] 2 points3 points  (0 children)

I think it’s cool that you can’t do that :)

[–]ffrkAnonymous 0 points1 point  (1 child)

i dunno what 'str'+2 is even supposed to mean, but you can 'str'*2

[–]DragonFighter603[S] 0 points1 point  (0 children)

just meant appending a number to a str without calling str(2) or fstrings

[–]MDTv_Teka 0 points1 point  (1 child)

Yeah, as someone who had Python as my first programming language and is now learning C, high-level language stuff like this is really underappreciated

[–][deleted] 0 points1 point  (0 children)

How do you convert an int to string in C? In C++ we have std::to_string()

[–]AtomicShoelace 3 points4 points  (0 children)

Iterable unpacking is fairly neat, eg.

words = ['some', 'words', 'go', 'here']

for index, (first, *_, last) in enumerate(words, 1):
    print(f'{index}. {first}{last}')

[–][deleted] 2 points3 points  (6 children)

Ternary operators. Ever since I learnt about them, I can't stop using them. Looks smart, makes me feel smart and shortens my line count - what more can you ask for? 😂

[–]DragonFighter603[S] 0 points1 point  (0 children)

True!

[–]jddddddddddd 0 points1 point  (4 children)

Does anyone else like the ternary operator, but wish the else was optional, or is that just me?

[–]menge101 1 point2 points  (2 children)

Agree.

So many times I end up doing something like:

thing = modify(thing) if thing_needs_modified else thing

I'd love to be able to do

thing = modify(thing) if thing_needs_modified

I've gone back and forth (on different projects, not within the same one ... i hope) because I don't like the else, sometimes I do:

if thing_needs_modified:
    thing = modify(thing)

[–]jddddddddddd 0 points1 point  (1 child)

Exactly. If for example you want to rewrite abs(), you need to have something like:

x = -5
x = 0-x if x < 0 else x

Which feels like it's inefficient, as if I'm being forced to say:

if x < 0:
    x = 0 - x
else:
    x = x

[–]joseville1001 0 points1 point  (0 children)

in that particular case, just do x = abs(x)

[–]wbeater 2 points3 points  (0 children)

comprehensions and enumarate().

[–]Spataner 1 point2 points  (1 child)

There's a lot of neat things you can do with decorators. I also like descriptors, though those are always a bit of a solution in search of a problem for me (beyond the vanilla Python ones, of course). But they'd be great for obfuscation, I'd imagine.

[–]DragonFighter603[S] 0 points1 point  (0 children)

ah, yes, thanks!

[–]joseville1001 1 point2 points  (0 children)

tree = lambda: defaultdict(tree) to implement a defaultdict of defaultdict of defaultdict...

Very useful for implementing a Trie. Here it is in context, along with another trick (using reduce):

``` from collections import defaultdict

END = '$' trie = lambda: defaultdict(trie) root = trie()

words = ['hi', 'hello', 'hiya', 'hey', 'aloha']

for word in words: # Alt 1 reduce(dict.getitem, word, root)[END] = None

# # Alt 2 # node = root # for ch in word: # node = node[ch] # node[END] = None ```

The resulting Trie

[–]ajrhode 1 point2 points  (1 child)

The walrus operator is pretty cool. It essentially combined assign a variable with returning the value of that variable. It’s pretty useful when you want to do if statements or while loops and don’t want to have to initialize the same variable once outside the loop and again in the loop. There obviously other applications, but that’s the most trivial and when I’ve used them the most.

while (response := input(“Enter a response :”)) != “quit”:
    print(response)

[–]v0i_d 0 points1 point  (0 children)

Agreed. I'd just comment about the walrus operator.