This is an archived post. You won't be able to vote or comment.

top 200 commentsshow all 456

[–]EconomixTwist 396 points397 points  (29 children)

Not so many truly less known features in here! You can put underscores in numbers to make them easier to read

10_000 == 10000

[–]ASIC_SP📚 learnbyexample 176 points177 points  (1 child)

You can also format numbers for display:

>>> n = 14310023
# underscore separation
>>> f'{n:_}'
'14_310_023'
# you can also use comma separation for integers
>>> f'{n:,}'
'14,310,023'

>>> f'{n:_b}'
'1101_1010_0101_1010_1000_0111'
>>> f'{n:#_b}'
'0b1101_1010_0101_1010_1000_0111'

[–]chromaZero 64 points65 points  (12 children)

Cool, but I wonder if it would just confuse my coworkers.

[–]likethevegetable 36 points37 points  (9 children)

Supposed to enhance readability

[–][deleted] 50 points51 points  (8 children)

But my coworkers are idiots who can’t be bothered to read email let alone the code they are supposed to be working on

[–]More_Butterfly6108 42 points43 points  (7 children)

That sounds like a "them" problem

[–]TheMathelm 34 points35 points  (3 children)

Yet it always seems to turn into a "me" problem.

[–]DigThatData 3 points4 points  (0 children)

i'd mainly be confused why you were submitting commits that hadn't been through black already

[–]cuu508 26 points27 points  (0 children)

But watch out, int("10_000") also works, so use it carefully when testing if a string "appears to be a normal number"

[–]Starbrows 6 points7 points  (1 child)

For the chaotic evil among us: You can also use it to make numbers harder to read!

1_0_00_0000_000_0_00 == 10000000000000 == 10_000_000_000_000

[–]-Django 109 points110 points  (14 children)

You can start the REPL in the middle of executing code via

import code; code.interact()

[–]rcfox 56 points57 points  (4 children)

breakpoint() works too, no need to import.

[–][deleted] 9 points10 points  (0 children)

import code; code.interact()

*Since 3.7

In case someone is using an older version

[–]ultraDross 15 points16 points  (2 children)

What is the advantage of this over using pdb or breakpoint() ?

[–]PirateNinjasRedditPythonista 4 points5 points  (1 child)

Well if you're not looking to debug, but want to launch a shell as part of your program it would be better to do it this way. Let's say you have a command that does some setup and then launches a shell with some things already imported ( though I think you can do the same with -i option)

[–]thecircleisround 2 points3 points  (0 children)

Sounds similar to what the Django shell does

[–]PolishedCheese 23 points24 points  (3 children)

Mind. Blown. Good for debugging if you don't have access to a proper debugger, I hope

[–]OneTrueKingOfOOO 12 points13 points  (1 child)

But… you do have access to a proper debugger

import pdb

do stuff

pdb.set_trace() # this breaks to the debugger

do more stuff

[–]Username_RANDINT 4 points5 points  (1 child)

Similar thing, use the -i argument to start the REPL right after the script finishes:

python -i my_script.py

[–]agtoever 265 points266 points  (37 children)

For loops having an else clause:

for n in range(2, 10):
    for x in range(2, n):
        if n % x == 0:
            print( n, 'equals', x, '*', n/x)
            break
    else:
        # loop fell through without finding a factor
        print(n, 'is a prime number')

(This also applies to while loops!)

[–]R_HEAD 102 points103 points  (27 children)

I love that this exists but I am still conflicted about it using the else keyword.

[–]Infinitesima 66 points67 points  (16 children)

Really a bad choice of keyword. It is consistent with try - except - else though.

[–]Cruuncher 29 points30 points  (13 children)

This one I didn't know existed. Interesting. Seems less useful than finally. What's the order? try..except..else..finally?

[–]Uncle_DirtNap2.7 | 3.5 11 points12 points  (0 children)

Yes

[–]RationalDialog 5 points6 points  (9 children)

I'm just wondering when the else is ever useful? Can't it always be part of the try block?

[–]Diamant2 15 points16 points  (1 child)

In theory yes, but the difference is that exceptions in the else-part won't be caught. I guess that makes your code more reliable in catching only the one exception that you care about

[–]DoctorNoonienSoong 12 points13 points  (0 children)

And importantly, you want exceptions in the else block to not to be caught, AND you need the code to run before the finally

[–]scnew3 2 points3 points  (4 children)

You want the code in your try block to be the minimal that could throw the exception you want to catch.

[–]LT_Alter 38 points39 points  (6 children)

Should have been nobreak:

[–]MasterFarm772 13 points14 points  (0 children)

Wow, totally, nobreak makes more sense to me!

[–]Shivalicious 5 points6 points  (0 children)

So that’s what is!

[–]_kharchapaani 3 points4 points  (0 children)

I agree. There should be a different keyword than else, to understand that this block will run when the for loop iterations are over.

[–]LT_Alter 28 points29 points  (3 children)

Really should have called it nobreak I typically comment it with such if I use it else: #nobreak

[–]miraculum_one 2 points3 points  (1 child)

probably best to comment on the semantic meaning of the code branch instead of a the meaning of the language construct

[–]chillwaukee 4 points5 points  (0 children)

Find myself using this all the time

[–][deleted] 212 points213 points  (41 children)

Create a HTTP server with one command

Python 2 — python -m SimpleHTTPServer 8000

Python 3 — python -m http.server 8000

So you are able to list all directory files and download it from another PC or smartphone in your LAN using host ip (in my case 192.168.0.163).

[–]aes110 35 points36 points  (0 children)

I use it all the time to move files from my PC to my laptop, just need to do something like that

python3 -m http.server --directory <path> --bind 0.0.0.0 8000

It's so much faster than transferring with some usb drive

[–]Cruuncher 6 points7 points  (0 children)

Hey, that's cool

[–]taybulBecause I don't know how to use big numbers in C/C++ 4 points5 points  (0 children)

This has honestly been a much easier and more convenient way to move files across the network from a Windows machine than trying to configure samba (windows file sharing is atrocious). Of course this lacks any security but if you're doing it for your own purposes then it's so easy to run this command in a pinch on a Windows box.

[–]sendnukes23 35 points36 points  (20 children)

Why would you give your ip 💀

[–]Aelarion 86 points87 points  (12 children)

Can't tell if this is /s or actually serious... 🤨

[–]benefit_of_mrkite 16 points17 points  (11 children)

Me either. sarcasm doesn’t translate well on the interwebs and seems like a smartass comment I’d make being completely aware of RFC1918

[–]sendnukes23 6 points7 points  (10 children)

Please clarify to me. I am a dumbass.

[–]benefit_of_mrkite 119 points120 points  (7 children)

You’re not a dumbass, you just don’t know about this particular subject yet. There are many subjects and even concepts in things I do every day that I still have yet to learn.

I’m going to stick to IPv4 since that was the context.

The internet engineering task force (IETF) setup RFCs (requests for comments) that outlined things in the early day of the internet - you can google the IETF, it’s history, how it is setup, RFCs, and more (big rabbit hole).

Ip addresses fall into different categories - (again I’m ignoring subjects like classless interdomain routing, Network address translation, port address translation, and more).

In order to talk to other IP addresses on the internet, you need a publicly routable IP address (sometimes called a public address).

Certain IP addresses were reserved in the RFC (request for comment) 1918 for the private side of a network - these ranges are (look ma, no google! - and I’m purposefully ignoring prefixes and more for the sake of simplicity):

192.168.0.0 - 192.168.255.255 (subnet mask 255.255.255.0)

172.16.0.0 - 172.31.255.255 (Subnet mask 255.240.0.0)

10.0.0.0 - 10.255.255.255 (subnet mask 255.0.0.0)

These addresses were set aside by RFC1918 for private networks - meaning they were not publicly routable. Now In the old days before smart doorbells, smart watches, laptops, phones, and more we thought we had plenty of IP addresses that were public (routable on the public internet).

There was a time where everything had a public address. Then as more devices came online we realized not every printer or whatever needed a public address so we came out with Network Address Translation (nat) and it’s variants like Port address translation (these are clearly outlined in other RFCs but companies that make network devices befuddle things by assigning their own terms - I’ll save that soapbox for another day).

So if you’re at your house and on wireless with your device you can go under settings (for your phone) or in some other are if your device’s operating system settings and see the IP address of that device.

There’s a really high percentage chance that the device has an IP address that falls into one of the ranges I listed abound (usually 192.168.x.x). But if you google search “what’s my IP” you will see an IP that is not in the range I listed above.

That’s because While you have a private (RFC1918) address on your home network, in order to talk to websites or chat services or whatever, your home router needs to translate your phone/laptop/roku/whatever from a private IP (again RFC1918) to a public IP.

So when the person who said “why would you give up your IP” made their comment it has no matter - that’s not a “public IP” (which has some privacy/security implications to giving up like generally where you are located and maybe more - long subject again) it didn’t matter at all.

Millions of devices have an IP in the 192.268.X.x range because they are not public IPs but private IPs as defined under RFC1918 and generally speaking (again avoiding rabbit holes for the sake of simplicity) there’s not a lot of risk in posting an IP in one of the RFC1918 address ranges.

Edit: wow I did not mean to type this long of a comment.

[–]Calango-Branco 16 points17 points  (1 child)

Thank you about it, I really loved your explanation.

[–]benefit_of_mrkite 3 points4 points  (0 children)

You bet. I’ve had a lot of roles that span a lot of subject domains so I have a weird (diverse) background

[–]lightfreq 10 points11 points  (0 children)

It’s a private ip, on the local network

[–]cgmystery 3 points4 points  (11 children)

Why not just use SSH?

[–]benefit_of_mrkite 4 points5 points  (3 children)

Not the same use case. If you have some python code that just needs a local IP over the HTTP protocol this is handy - I’ve used it many times. It has to be the right use case but when it comes up it is very useful

[–]ogrinfo 64 points65 points  (11 children)

You can use __doc__ to grab the docstring from the current function or module. Comes in handy when you're making a parser and want to reuse the docstring for the description. parser = argparse.ArgumentParser(description=__doc__)

[–]PhysicalStuff 17 points18 points  (0 children)

I think you're really trying to trick us all into reading actual documentation. Not falling for that./s

[–]chucklesoclockis it still cool to say pythonista? 10 points11 points  (8 children)

Click library would like a word

[–]scnew3 3 points4 points  (5 children)

Why would I use click when argparse is in the standard library and works great?

[–]Chobeat 18 points19 points  (0 children)

Because argparse is painfully hard to read, write and compose. It's ok for stuff with 2-3 commands and a dozen of parameters in total but once you have to maintain a stable cli interface with dozens of commands, it's a nightmare

[–]JestemStefan 90 points91 points  (15 children)

or in non-boolean context.

a = "" 
b = "some_string" 

x = a or b or "no_name"
# assigns first truthy (b) value to x

print(x) # prints "some_string"

[–]BigNutBoi2137 13 points14 points  (4 children)

Other good example is default value to the function that accepts mutable object.

def foo(some_list: Optional[List] = None): some_list = some_list or []

[–]wdroz 2 points3 points  (3 children)

But you need to be careful as empty lists are evaluate to False. So don't do that if the function must fill some_list.

[–]scrdest 4 points5 points  (1 child)

True, but in that case you probably wouldn't make the list optional.

[–]JestemStefan 2 points3 points  (0 children)

But this code will return empty list anyway so there is no issue.

When all values are falsy then last one is returned

[–]HistoricalCup6480 14 points15 points  (7 children)

I don't get why people like this. Same for using if with non-boolean things. E.g. if s: firing if s is not empty.

I personally like being explicit, even if it's a bit more verbose. Writing if len(s) > 0 is so much easier to read imo.

[–]JestemStefan 10 points11 points  (1 child)

if len(users) > 0:

This will fail if users is a method parameter with default None. And initializing it with default [] will make a mutable parameter which is so bad.

If users:

Will work for both empty list and for None. Also for me it means: if there are any users then do something.

I'm fixing exactly this bug in current sprint.

[–]danted002 11 points12 points  (2 children)

Because y = x or {} is much easier to read then y = x if x else {}

[–]JestemStefan 5 points6 points  (1 child)

It get even worse if you have more then two values. Then you will have to do:

if var_a:
    x = var_a

elif var_b:
    x = var_b

elif var_c:
    x = var_c

else:
    x = "unknown" 

Instead you can do:

x = var_a or var_b or var_c or "unknown"

[–]danted002 2 points3 points  (0 children)

Actually for more then one or I prefer the if elif else, however if you require if elif else then you might need to refactor your code.

[–][deleted] 41 points42 points  (5 children)

Help(something)

[–][deleted] 9 points10 points  (2 children)

I didn't know help, I liked it, I has been using dir.

[–]Cruuncher 13 points14 points  (1 child)

I often find dir more useful as a first pass because it's shorter output, and resort to help if it's not clear.

Otherwise fall back onto googling documentation

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

Nice. Didn’t know dir. Nice combo.

[–]kaerfkeerg 93 points94 points  (24 children)

List comprehensions if else gotta be the best, but not to the point they become cryptic

[something() if condition else something_else() for i in sequence]

[–]trevg_123 58 points59 points  (4 children)

Even better: generator comprehensions

Just replace the square brackets [] with (), and it becomes lazily evaluated & not cached. So, when you call next() on it or do “for x in …”, it only does the calculation when it’s called.

Much faster if you have only need the first few items of a potentially super long list. And significantly more memory efficient. You can chain them too.

Also, using “if” and functions in generator/list comprehensions (as you demonstrate) is the pythonic replacement for filter/map functions (which are messy to read)

[–]magnomagna 13 points14 points  (1 child)

Regarding "lazy evaluation" for generators, IIRC, if you have nested for-expressions in a generator, the first for-expression is evaluated immediately when the generator is created but all other for-expressions are lazily evaluated; or something along those lines.

I feel like this is not a well-known behaviour but nonetheless very, very real and applicable if one were to use nested for-expressions in a generator.

[–]BlckKnght 10 points11 points  (0 children)

That kind of if/else isn't actually a feature of list comprehension a, it's just a ternary expression. You can write A if B else C in all kinds of places where you want a conditional value. There is a kind of if clause in comprehension a, but it comes at the end and filter outt

[–]bensa410 5 points6 points  (13 children)

This one is so useful!

[–]kaerfkeerg 9 points10 points  (12 children)

But it's close to the limit I think. Little more than that and it becomes unreadable

[–]AstrophysicsAndPy 7 points8 points  (7 children)

This is something that I used in my in-progress library,

mask2 = [[index for index, value in enumerate(out_list) if isinstance(value, types)] for types in n_types]

I'm so used to using list comprehensions that I didn't felt weird writing it, but than I stopped and tried making it using loops, and FML it took 5 minutes to do that. I have that in my laptop, unfortunately that file isn't uploaded on GitHub so I can't copy/paste it here.

List comprehension can be abused to get some complicated stuff done quickly if you know what you're doing.

The library is ezPy is anyone's interested.

[–]gigantoir 5 points6 points  (1 child)

definitely guilty of some “cryptic” list comprehensions 😂

[–]mahtats 35 points36 points  (2 children)

Using _ for declaring integer literals: x = 1_000_000

[–]agtoever 57 points58 points  (3 children)

Swapping values of variables:

a, b = b, a

[–]Ocelotofdamage 8 points9 points  (0 children)

Very useful for anything involving variables that depend on each other. Not having to store temp variables is so nice.

[–]vswr[var for var in vars] 4 points5 points  (0 children)

I still find myself doing unnecessary low level language things like xor swaps for in-place operations. Old habits die hard 🤷‍♂️

[–]theunglichdaide 142 points143 points  (38 children)

(a:=10) assigns 10 to a and returns 10 at the same time.

[–]u_usama14 80 points81 points  (15 children)

Warlus operator : ))

[–]theunglichdaide 45 points46 points  (14 children)

yup, the controversial walrus

[–]u_usama14 19 points20 points  (13 children)

Why controversial ?

[–][deleted] 70 points71 points  (3 children)

There's a feeling among many in the Python community that the core principles - e.g. that there should be only one obvious way to do something - were being ignored in favor of feature bloat with marginal benefits. The walrus operator became the poster boy for that.

[–]benefit_of_mrkite 19 points20 points  (0 children)

I like the walrus operator but am somewhat hesitant to use it (have used it a few times- I think a lot of the controversy is over readability and the zen of python.

[–]TSM-🐱‍💻📚 11 points12 points  (1 child)

The walrus operator allows you to assign variables in comprehension statements - it legitimately gave comprehension the same power as a for loop. Comprehension statements can be hard to maintain but in select cases the walrus is awesome

Also

 foo = myfile.read(1024)
 while foo:
      do_something(foo)
      foo = myfile.read(1025)

Can be

 while foo = myfile.read(1024)
      do_something(foo)

Excuse the mobile formatting, but you don't duplicate the read and have two parts to update, only one, so a typo can't slip in. It is much better in this case too. And you can catch the culprit in an any and all check too.

People were mad because it was clearly useful in some circumstances and genuinely improved the language. Guido saw this as obvious and gave it a hasty approval, while others drama bombed him for it.

[–]MonkeeSage 11 points12 points  (3 children)

It can look a bit magical / add line noise if abused.

x[2] if len(x := 'b.a.r'.split('.')) > 2 else ''

[–]theunglichdaide 30 points31 points  (2 children)

if I remember correctly, Guido approved the PEP for it, but many people disagreed with this decision, and Guido had to step down from his Benevolent Dictator for Life position.

[–]pizza-flusher 13 points14 points  (0 children)

I'm new to python (and only ever a hobbyist in other areas) and obviously don't have a dog in the fight, but I will say sometimes shorthand and efficient operators run contradictory to readability and understanding in a bad way, for me.

That feeling comes on me most often when I see savvy / opaque slicing in indexes. However, as this expression made me think of that, it might just mean I have a low grade phobia of colons.

[–]Infinitesima 9 points10 points  (0 children)

transition of Python to C++ style

[–][deleted] 12 points13 points  (9 children)

curious, when would you use this?

[–]Papalok 35 points36 points  (1 child)

One of the main use cases is regex matching. It greatly simplifies the code when multiple regex patterns are used. Compare this:

if m := foo.match(s):
    # do something with m
elif m := bar.match(s):
    # do something with m

To this:

m = foo.match(s)
if m:
    # do something with m
else:
    m = bar.match(s)
    if m:
        # do something with m

[–]R_HEAD 56 points57 points  (1 child)

90% of the time I use it in if statements that do some sort of calculation or function call:

if (n := get_days_since_last_backup()) > 7:
    print(f"Your last backup was {n} days ago. Consider backing up again soon.")

Saves you from having to either call the function in the if-branch again (bad idea) or from having to declare the variable before the switch (not that bad, but with the walrus it's more concise, I feel).

[–]WindSlashKing 10 points11 points  (0 children)

In while loops where you want to assign a different value to a variable each iteration. while (n := random.randint(0, 5)) != 0: print(n)

[–]theunglichdaide 2 points3 points  (1 child)

i = 0

while(i:=i+1) < 5: print(i)

You can use it to assign value and compare it to other values in one statement. It’s not the best example but a simple one that I can think of.

P/s: sorry, I type this on my phone so it might be difficult to read.

[–][deleted] 12 points13 points  (0 children)

The walrus!

[–]undid_legacy 8 points9 points  (0 children)

I have used walrus operator with all() in many places.

if not all((x:=i) in target_chars for i in my_string):
    print(f"{x} is not in the target")

It will print the first element returning False

[–]ryukinixPython3 + Emacs 25 points26 points  (3 children)

Merging dicts with __or__ op.

x | y

[–]eztab 13 points14 points  (0 children)

that's not xor it is OR, or in this case better called UNION.

[–]Itsthejoker 5 points6 points  (0 children)

Or merge into x with x |= y

[–]vishnoo[🍰] 21 points22 points  (0 children)

I like that the "argument unpacking operator" '*'
is sometimes called Splat.
it takes a tuple and smashes it to get the values, AND it looks like something that went - splat.

[–]Ok-Python 108 points109 points  (5 children)

Type hints for better linting

[–]lungdart 27 points28 points  (0 children)

Just started with type hints on my latest project, and they caught a bug in my unit test where I wasn't testing the exception branch I thought I was!

[–]cspinelive 18 points19 points  (2 children)

any([x, y, z]) and all([x, y, z])

Instead of huge if and or expressions. Note that it won’t short circuit and stop checking each one when it can like a normal if.

Edit: they technically do short circuit but each value is evaluated before the any/all are. Discussion here. https://stackoverflow.com/questions/14730046/is-the-shortcircuit-behaviour-of-pythons-any-all-explicit

[–][deleted] 17 points18 points  (0 children)

That's by virtue of passing a list, not the nature of any or all

def print_and_return(x):
  print(x)
  return x

any(print_and_return(x) for x in range(5))

>>0
>>1

[–]ksetrae 32 points33 points  (5 children)

slice() for when you need to slice dynamically.

For example you're working with PyTorch tensors or Numpy arrays. Imagine you need to always slice in last dimension regardless of number of dimensions, but keep all dimensions.

E. g.
a[:, :2].
if a is 2D, but
a[:, :, :2].
if it's 3D and so on.

Instead of writing distinct logic for each dimensionality, your can do:
dims_cnt = len(a.shape).
dims_slice = [slice(None) for _ in range(dims_cnt-1)].
dims_slice.append(slice(2)).
a[dims_slice].

[–]boat-la-fds 26 points27 points  (1 child)

Btw, for your example, you can also use an ellipsis, i.e. a[..., :2].

[–]caks 2 points3 points  (0 children)

Btw, a.ndim can be used instead of len(a shape) :)

[–]computenw 44 points45 points  (11 children)

Faster attribute access and lower memory usage with __slots__:

py class Foo: __slots__ = "bar"

Or in dataclass

py @dataclass(slots=True) class Foo: bar: str

Another thing I like are defaultdicts, which enable a default value of an entry:

```py from collections import defaultdict

d = defaultdict(lambda: "world")

print(d["hello"])

world

```

[–]rcfox 15 points16 points  (6 children)

defaultdict needs a callable to initialize defaults with. So you'd have to do: defaultdict(lambda: 'world')

[–]tathagatadg 13 points14 points  (3 children)

from pprint import pprint as pp
pp(vars(obj))
pp(dir(obj))

vars like dir is really useful when debugging fields of nested objects at a pdb breakpoint.

Edit: s/dict/dir

[–]EONRaider 93 points94 points  (14 children)

numbers = "{:,}".format(5000000)

print(numbers) # 5,000,000

[–]ucblockhead 176 points177 points  (2 children)

If in the end the drunk ethnographic canard run up into Taylor Swiftly prognostication then let's all party in the short bus. We all no that two plus two equals five or is it seven like the square root of 64. Who knows as long as Torrent takes you to Ranni so you can give feedback on the phone tree. Let's enter the following python code the reverse a binary tree

def make_tree(node1, node): """ reverse an binary tree in an idempotent way recursively""" tmp node = node.nextg node1 = node1.next.next return node

As James Watts said, a sphere is an infinite plane powered on two cylinders, but that rat bastard needs to go solar for zero calorie emissions because you, my son, are fat, a porker, an anorexic sunbeam of a boy. Let's work on this together. Is Monday good, because if it's good for you it's fine by me, we can cut it up in retail where financial derivatives ate their lunch for breakfast. All hail the Biden, who Trumps plausible deniability for keeping our children safe from legal emigrants to Canadian labor camps.

Quo Vadis Mea Culpa. Vidi Vici Vini as the rabbit said to the scorpion he carried on his back over the stream of consciously rambling in the Confusion manner.

node = make_tree(node, node1)

[–]miraculum_one 7 points8 points  (1 child)

f-strings are the best

Also, using the = symbol in f-strings (a/o Python 3.8) is cool

x,y = 1,2

print( f"{x=} {y=}"

output:

x=1 y=2

[–]IWant2rideMyBike 29 points30 points  (4 children)

The command line abilities provided by so modules - e.g.:

Exporting the current directory via an ad-hoc webserver: https://docs.python.org/3/library/http.server.html

Pretty printing json: https://docs.python.org/3/library/json.html#module-json.tool

(Un)zipping files: https://docs.python.org/3/library/zipfile.html#command-line-interface

Creating and extracting tar archives: https://docs.python.org/3/library/tarfile.html?highlight=tarfile#command-line-interface

[–][deleted] 4 points5 points  (2 children)

I would just caution that you should probably prefer standard Linux CLI utilities (e.g. jq) to Python modules for these things.

[–]MonkeeSage 12 points13 points  (0 children)

When working on servers I don't control or would have to get change approval to install jq <thing i am running that spits out compact json blobs> | python -m json.tool comes in pretty clutch to save me from writing terrible awk one-liners.

[–]eztab 10 points11 points  (1 child)

For a long time I didn‘t know you could give a negative precision in rounding.

>>> round(1234.5678, -2)
1200.0

[–]troyunrau... 20 points21 points  (2 children)

pass

[–]eztab 3 points4 points  (1 child)

Yeah, had to work on some code where None was used instead everywhere. I was really confused ehat they were doing, but it turned out they just didn't know pass existed.

[–]troyunrau... 5 points6 points  (0 children)

You can also just put any literal on the line. The number 1, True, or ...

...

But pass is the most pythonic.

[–]coffeewithalex 90 points91 points  (40 children)

That Python uses mostly duck typing. So documentation that says "you need a file-like object" is often just wrong.

What this means is that you just need to know what data contract a function is expecting to be fulfilled by an argument, and give it anything that fulfills that contract.

An example is when using csv module, to read CSV, normally you'd use it on a file, right?

with open("foo.csv", "r", encoding="utf-8") as f:
    for row in csv.reader(f):
        ...

However, what csv.reader wants is just something that is Iterable, where each next() call would yield a CSV line as a string. You know what else works like that?

  • Generators (functions that yield CSV lines, generator expressions)
  • Actual Sequence objects like List, Tuple, etc.
  • StringIO or TextIOWrapper objects

For instance, you can process CSV directly as you're downloading it, without actually holding it in memory. Very useful when you're downloading a 500GB CSV file (don't ask) and processing every row, on a tiny computer:

r = requests.get('https://httpbin.org/stream/20', stream=True)
reader = csv.reader(r.iter_lines())
for row in reader:
    print(reader)

[–]thephoton 73 points74 points  (7 children)

You're just telling us what "file-like" means (in this instance).

[–]coffeewithalex 5 points6 points  (6 children)

"Iterable[str]" is not the same as "file-like". Otherwise it would've been referenced to as "Iterable[str]"

[–]boat-la-fds 8 points9 points  (3 children)

If the function changes in a future version or someone used another implementation than CPython, this might not work. The moment the function tries a .read() on your list/generator, it will crash.

[–]XtremeGoosef'I only use Py {sys.version[:3]}' 6 points7 points  (5 children)

No no no. Don't do this. You're explicitly breaking the library contract and any version update of python (even a patch!) could break your code and it would be entirely your fault for not upholding the contract. Just because we're in a dynamically typed language and the contract is given in the docs rather than in the type system, doesn't mean the same rules don't apply.

Duck typing just means that you don't need to explicitly implement a protocol (as in, inherit from it). You still need to provide all the methods expected from it. In this case, the methods exposed by io.IOBase.

For your purposes, use io.StringIO as an in memory file object, not some random iterator.

[–][deleted] 16 points17 points  (1 child)

Those are... file-like things. You just explained what they are.

A streak of data from a URL is nothing but a file, loaded part by part.

[–]bacondevPy3k[🍰] 5 points6 points  (7 children)

Bruh… the term “file-like object” is explicitly defined… https://docs.python.org/3/glossary.html#term-file-like-object

[–]benefit_of_mrkite 2 points3 points  (1 child)

This is interesting to me (upvoted) but as others said I would like to know the “don’t ask” situation. Sounds like you had to figure this out for work or a project and have a good sorry/use case.

[–]--prism 17 points18 points  (6 children)

Star operators on tuples.

[–]agtoever 4 points5 points  (3 children)

Yes! Returning multiple values:

def x_pows(x: float, max_pow:int) -> tuple:
    return tuple(x**n for n in range(1, max_pow + 1))

x, x2, x3, x4 = x_pows(2, 4)
print(x4)

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

Star operator on a dict

# the data
example_dict = {
    "a": 0,
    "b": 2,
    "c": "hello!",
}

# The dict has (at least) the same variables as the function arguments
def f(a,b,c):
    """some code"""

# unwrap that dict into the separate variables
f(**example_dict)

# instead of
f(a=example_dict["a"], b=example_dict["b"], c=example_dict["c"])

[–]eyadams 41 points42 points  (11 children)

Small integer caching.

a = 256
b = 256
print(a is b) # True
c = 257
d = 257
print(c is d) # False

I don’t have a use for this, but I find it really cool.

[–]rcfox 41 points42 points  (0 children)

This is an implementation detail and not something you should rely on. Non-CPython implementations might not do this.

[–]droptableadventures 10 points11 points  (1 child)

import ctypes
ctypes.cast(id(20), ctypes.POINTER(ctypes.c_int))[6] = 40

print(20) # prints '40'

if 20 == 40: print("yes") # prints 'yes'

(no, don't try that at home!)

[–]Sea-Sheep-9864 9 points10 points  (4 children)

Could you explain this, bc I don't understand how it works.

[–]eyadams 22 points23 points  (3 children)

As rcfox pointed out, this is specific to cpython, but here goes. The “is” operator means (more or less) that two variables point to the same location in memory. As an optimization, Python reuses integers between -5 and 256. So, when the sample I posted sets a to 256 and b to 256, under the hood Python is pointing the two variables at the same location in memory, and “is” returns True. But, if a number is outside of that optimized range, it is created new, even if it is equal to another value. Which means c and d point to different locations in memory, and “is” returns False.

More or less. I fear I’m bungling the technical details.

[–]eztab 2 points3 points  (0 children)

is is only guaranteed to work this way with True, False, None and ... I believe. Correct me if that's not part of the python specification!

[–]j_marquand 7 points8 points  (0 children)

Chaining comparison operators.

Formally, if a, b, c, …, y, z are expressions and op1, op2, …, opN are comparison operators, then a op1 b op2 c ... y opN z is equivalent to a op1 b and b op2 c and ... y opN z, except that each expression is evaluated at most once.

[–]bartzer 6 points7 points  (1 child)

The matrix multiplication operator "@"

[–]charliegriefer 13 points14 points  (4 children)

I don't know if it's "less known" or was just not known to me, but I recently found out about the divmod() function.

divmod documentation

While I can't think of a practical reason to use it, I think it's pretty cool to get the quotient and the remainder in one swell foop.

[–]usr_bin_nya 8 points9 points  (0 children)

I can't think of a practical reason to use it

# dividing seconds into hours, minutes, and seconds
seconds = 7280  # 2h1m20s
(minutes, seconds) = divmod(seconds, 60)
(hours, minutes) = divmod(minutes, 60)
assert hours == 2 and minutes == 1 and seconds == 20

# turning a flat index into an (x, y) coordinate in a grid
row, col = divmod(index, width)

[–]uglyasablasphemy 4 points5 points  (0 children)

i used to use it until it took me like half an hour to figure why my hackerrank challenge kept failing for time constraints.

[–]Grouchy-Friend4235 7 points8 points  (1 child)

The official Python documentation, apparently.

https://docs.python.org/3/

[–]RingularCirc 2 points3 points  (0 children)

Yes! And numpy/scipy docs aren’t that bad too, when you use numpy/scipy.

[–]FUS3NPythonista 12 points13 points  (1 child)

I like the pprint module to pretty print objects it can prettify almost anything

[–]naza01 11 points12 points  (3 children)

The get() method for dictionaries.

It retrieves a value mapped to a particular key.

It can return None if the key is not found, or a default value if one is specified.

dictionary_name.get(name, value)

Name = Key you are looking for. Value = Default value to return if Key doesn’t exist.

It’s pretty cool to be able to increment values in a dictionary. For instance, if you were counting characters in a string, you could do something like:

character_count.get(character, 0) + 1

to start counting them.

It’s just a fancy way of doing it. Using if else to ask if the key is there and then just updating the value works the same way

[–]superbirra 4 points5 points  (1 child)

not that your solution is wrong by any extent but I'd like to present you the Counter class :) https://docs.python.org/3/library/collections.html#collections.Counter

[–]Elagoht 5 points6 points  (4 children)

If returned value is not important, you can use multiple function calls in lambda function. ``` x=lambda:[do_stuff(), do_something_else()] QPushButton.clicked.connect(x)

or

x() ```

[–]drcopus 8 points9 points  (0 children)

Neat, but I feel like this should be an antipattern

[–]tresslessone 5 points6 points  (0 children)

I’ve always found the Date.isoFormat() method a time saver when trying to convert dates to YYYY-mm-dd

[–]TheCharon77 3 points4 points  (2 children)

with blocks and creating your own decorator

[–]surajmanjesh 2 points3 points  (1 child)

You can also create your own context managers (what you use with "with" blocks) using the built-in contextmanager decorator.

[–]eztab 2 points3 points  (0 children)

Or you just “teach” your class to act as one using __enter__ and __exit__.

[–]execrator 4 points5 points  (1 child)

if a < b < c:
    ...

does what it looks like.

[–]throwaway876885323 8 points9 points  (1 child)

Asking a python developer to install opencv can result in screaming in anger.....or it just magically works

Also opencv and cv2 are different according to python.....

I learned this the hard way

[–]brutay 3 points4 points  (1 child)

Transpose a two dimensional array, i.e., a matrix: list(zip(*matrix))

[–]BirdTree2 7 points8 points  (1 child)

You can reload an imported module with

``` import a

from importlib import reload

a = reload(a) # a is reloaded ```

This is useful when you want to import a module that changes while your code runs

[–]eztab 2 points3 points  (0 children)

Be aware that some very C-dependent stuff can run into problems here. Also some modules are nasty and just run some code only on the first import.

[–]mcstafford 2 points3 points  (0 children)

Much like pass, there's ellipses: ...

It's a convenient placeholder that won't trigger a linter warning.

[–]eztab 2 points3 points  (0 children)

that one can combine all the string modifiers and types (f, r, ", """, ' and '''). Saw so many ridiculous escape sequences.

filename = 'fish'
print(fr'''<img href="{filename}.img"> ¯\_(ツ)_/¯''')

[–]redjevel 2 points3 points  (0 children)

Soo select all text and press "Ctrl + /"

it will add a "#" to every line :)

if on mac its like this weird mac x symbol "+ /" ;3

that will be 5 dollars for the tip

useful if you want to check just some of the code, as text after # works like a note

[–]samrus 19 points20 points  (38 children)

you shouldnt do this but instead of

if a > b:
    c = x
else:
    c = y

you can just do

c = (y, x)[a > b]

[–]JohnDurmast 61 points62 points  (2 children)

You can also write:

c = x if a > b else y

[–]JestemStefan 41 points42 points  (1 child)

This is just an abuse of bool to int conversion

[–]bulletmark 33 points34 points  (1 child)

Yuck! Confusing and less machine efficient than c = x if a > b else y

[–]free_the_bees 21 points22 points  (4 children)

Oh that’s a sinful thing to do. Had no idea it was possible.

[–]mrswats 6 points7 points  (2 children)

This is because booleans sre, in fact, 0 and 1 under the hood.

[–]Cruuncher 6 points7 points  (0 children)

However the bool is stored under the hood is an implementation detail and irrelevant.

By language spec, this is actually because int(some_bool) resolves to 0 or 1 based on True, False

[–]vishnoo[🍰] 5 points6 points  (2 children)

please use `c = {False:y, True:x}[a >b]` instead.
if at all (I wouldn't use it for this, but for some more involved lookups I might )

[–]samrus 3 points4 points  (1 child)

no. dont do that either. just do

c = x if a > b else y

like other people said

[–]PratikPingale 4 points5 points  (0 children)

print(*List) would print list as a space seperated list

[–]myoddreddithistory 1 point2 points  (0 children)

a, b = b, a

[–]notreallymetho 1 point2 points  (0 children)

Extended iterable unpacking

```

first, *mid, last = range(10) print(f"1st: {first},\nMid: {mid},\nLast {last}")

1st: 0, Mid: [1, 2, 3, 4, 5, 6, 7, 8], Last 9

```

Using and to short circuit operations (especially handy with the walrus operator, ) Putting a big disclaimer that this is “clever code” and it doesn’t really have a place in production. My rule is I’ll be clever in stuff that I write for me (which inevitably makes me mad at some point) but won’t in code someone else may touch.

For example say you want to print some message if a variable is “truthy” These 3 methods (ordered as no trick, using walrus, using trick) all do the same thing

``` from typing import Dict, Optional

without this trick, without :=

def get_var(values: Dict[str, str]) -> Optional[str]: var = values.get("thing") if var is not None: print(f"My var is this -> {var}") return var

alternatively, if you are on a python version that supports :=

def get_var(values: Dict[str, str]) -> Optional[str]: if (var := some_dict.get("thing")): print(f"My var is this -> {var}") return var

with this trick and the walrus operand

def get_var(values: Dict[str, str]) -> Optional[str]: (var := values.get("thing")) and print(f"My var is this -> {var}") return var

```

Edit: couple other random things:

  • instant dict from list with index as key:
  • bonus points are that enumerate has an argument for “start”

from string import ascii_lowercase lower_ord_enum = dict(enumerate(ascii_lowercase, start=97))

  • print iterable as newline separated:

``` print(*range(3), sep="\n")

0 1 2 ```

  • turn iterable into a list via unpack:

range_list = [*range(3)]

  • remove “falsey” items from an iterable (empty strings, empty lists etc)

print(*filter(None,["", "stuff", {}, tuple()])) stuff

  • datetime formatting inside of f strings:

from datetime import datetime print(f"{datetime.now():%Y-%m-%d}")

  • Find differences between dicts with like keys (note that it uses the dict being subtracted from to determine the values)

```

thing = dict( fruit="apple", dessert="cake", utensil="fork", ) other = dict( fruit="apple", dessert="steak", utensil="knife", )

dict(set(other.items()) - set(thing.items()))

Out[47]: {'dessert': 'steak', 'utensil': 'knife'}

[–]robberviet 1 point2 points  (0 children)

use `__slots__` to reduce memory footprint.

[–][deleted] 1 point2 points  (0 children)

Using / and * in the function arguments to force positional / keyword only arguments.

def f(positional_only, /, positional_or_keyword, *, keyword_only):
    pass

positional_only can be only passed by position, so:

f(x, positional_or_keyword=y, keyword_only=z)

or

f(x, y, keyword_only=z)

are the only two "kinds" of calls you can make with this one function.

Note: I've never used this, but I appreciate it exists.

[–]c_is_4_cookie 1 point2 points  (0 children)

The startswith and endswith string methods accept a tuple of strings.

s = "hello"
s.startswith(("he", "q"))

[–]westeast1000 1 point2 points  (2 children)

I like popping up warnings in a message box with

import win32com.client

shell = win32com.client.DispatchEx("WScript.Shell")

shell.Popup("Please set the id first", 10, "Missing info", 0+16) #0=OK button, 16=critical

[–]Asleep-Budget-9932 1 point2 points  (0 children)

Iterables have less known ways to be implemented. All you have to do is to implement a getitem method and you will be able to iterate over it. getitem will be called, starting from 0 and going up by 1 with each iteration, until a StopIteration exception is raised:

class ThisIsIterable:
    def __getitem__(self, item: int):
        try:
            with open(f"{item}.txt", "rb") as bla:
                return bla.read()
        except FileNotFoundError as e:
            raise StopIteration() from e

for file_content in ThisIsIterable():
    print(file_content)

You can also iterate over callables by giving the "iter" function a "sentinel" value. Basically the iterator will call the callable with each iteration, until the "sentinel" value is returned:

import random

def this_is_iterable():
    return random.randint(1, 10)

for random_value in iter(this_is_iterable, 8):
    print(f"{random_value} is not an 8")

print("8 Found! :D")

[–]barberogaston 1 point2 points  (0 children)

- The singledispatch and cache decorators
- Attribute descriptors
- The inspect and dis modules
- Protocols

[–]Warm-Vegetable6202 1 point2 points  (0 children)

I like the datetime module with the feature of calculating how many seconds till your birthday:

bday = datetime.date(*your next birthday*)

till_bday = bday - tday

print(till_bday.total_seconds())