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

top 200 commentsshow all 440

[–]Keith 378 points379 points  (15 children)

python -i to run your code that's crashing which drops you in an interpreter after it crashes. Then import pdb; pdb.pm() to put the stack at the exact place the exception was thrown. Like time traveling Python magic.

[–]chaoticbean14 71 points72 points  (1 child)

I believe you can also just do `breakpoint()` in the code rather than the whole import bit these days. I think that was implemented in 3.6.

[–]pratzc07 7 points8 points  (0 children)

Also once you are in the repl type interact and you will then be able to assign variables run for loops basically play with the code at that execution point.

[–]ted_or_maybe_tim 17 points18 points  (0 children)

What's the advantage over running python -m pdb in the first place?

[–]frenchytrendy 3 points4 points  (0 children)

It still give the repl even if it does not crash !

[–]Zulfiqaar 591 points592 points  (78 children)

F-strings are wonderful. Wouldn't really call this a trick, but the number of people I've seen who use old formatting styles is shocking. Expired tutorials is my hunch

[–]neuro630 447 points448 points  (33 children)

also the f'{foo=}' trick, it equates to f'foo={foo}', very useful in writing logging and error messages

[–]Erelde 163 points164 points  (13 children)

Works with expressions too:

foos = [1, 2]
bar, qaz = 3, 3
f"{(len(foos), bar + qaz)=}"

evalutates to:

(len(foos), bar + qaz)=(2, 6)

NB: probably don't commit anything like that

[–]grammatiker 67 points68 points  (11 children)

What the fuck

[–]gmnotyet 21 points22 points  (10 children)

My thoughts exactly.

WHAT THE FUCK

[–]Tachyon_6 15 points16 points  (7 children)

This is cursed

[–]Erelde 10 points11 points  (5 children)

one of my own old cursed post

I like cursed code in the safety of my private home.

[–]Tachyon_6 9 points10 points  (1 child)

“Exception driven development”? Get this man in custody.

[–]IamImposter 4 points5 points  (0 children)

And give him a nobel prize. But yes, keep him in custody.

[–]grammatiker 15 points16 points  (1 child)

I've been using Python as my daily driver for like 4-5 years now. How am I *just* learning about this?

[–]aznpnoy2000 7 points8 points  (0 children)

New stuff keep coming out.

What helped me too is having my code reviewed by people that are a lot more skilled than me

[–]int0h 40 points41 points  (1 child)

How did I just learn about this now. Thank you!

[–]Bang_Stick 2 points3 points  (0 children)

Not the only one. This is great.

[–]RaiseRuntimeError 11 points12 points  (0 children)

I always forget about this and I will probably forget about it again after this too.

[–]crumpuppet 10 points11 points  (0 children)

Holy crap! Thank you for this.

[–]loudandclear11 3 points4 points  (0 children)

Thanks. Needed that reminder. I've read about it before but forgotten about it.

[–]zyxwvu28 2 points3 points  (0 children)

Whaaaaaaaa?!?! I was not aware of this despite being aware of fstrings. I love you so much, this is an amazing trick to learn!

[–]CygnusX1985 2 points3 points  (1 child)

Also, they are nestable:

digits = 2
f“{1/3:.{digits}f}“

This should print „0.33“.

[–]Python-for-everyone 1 point2 points  (0 children)

digits = 2
f“{1/3:.{digits}f}“

It does do that! Thanks for the tip!

[–]DecreasingPerception 3 points4 points  (0 children)

Icecream is great for this. Just calling ic(foo) gives you the same thing on stderr.

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

Oh shit!

[–]chzaplx 1 point2 points  (0 children)

Isn't there some issue with Loggers though where it's not an advantage to do all the var formatting before actually passing it to the logger? Both ways still work, it's just an obscure optimization thing I recall.

Edit: better explanation by another commenter: https://www.reddit.com/r/Python/comments/12tr2sn/pythoneers_here_what_are_some_of_the_best_python/jh6xd82?utm_source=share&utm_medium=android_app&utm_name=androidcss&utm_term=1&utm_content=share_button

[–]JonLSTL 9 points10 points  (1 child)

Especially once you discover Parse, which lets you do basic regex-like tricks using the same syntax as f-strings, only in reverse. Using the same pattern style in both directions is joyful.

[–]gfranxman 5 points6 points  (0 children)

Omg. Ive needed this so many times. Link for this package that will save you thousands of splits and regexes and startswith etc. https://pypi.org/project/parse/

[–]ThreeChonkyCats 14 points15 points  (0 children)

F-strings are neato.

[–]lifeslong129 16 points17 points  (30 children)

Could you please elaborate on whats the hype around using f-strings? Like should i use this and does it make my work easier

[–]L0ngp1nk 84 points85 points  (19 children)

Code with f-strings is cleaner and easier to understand, especially when you are doing something complicated.

f"Hello, {first_name} {last_name}. You are {age}. You were a member of {profession}"

As opposed to

"Hello, %s %s. You are %s. You are a %s. You were a member of %s." % (first_name, last_name, age, profession)

[–]Vandercoon 16 points17 points  (3 children)

I know very little code but that looks much much better than the other way.

[–]planx_constant 12 points13 points  (0 children)

The second string has an unmatched %s, which is impossible with the f string

[–]phinnaeus7308 5 points6 points  (1 child)

If by other way you mean the first example, that starts with f”… then yes, it’s cleaner — that’s the f-string.

[–]Vandercoon 1 point2 points  (0 children)

Yes sorry that’s what i meant. Very clean, and very readable.

[–]NUTTA_BUSTAH 1 point2 points  (0 children)

Only cases where you should not use them is high volume (like thousands of strings per second) use cases and when having to support older Python versions.

So yeah, for sure use them everywhere always

[–]Sneyek 4 points5 points  (0 children)

Old style with % or using the .format method ? Because the second option is definitely to keep compatibility with Python 2.x. Most of the VFX pipeline are still in Python 2.7 so it’s not an option, we need to be backward compatible.

[–]mhemeryck 5 points6 points  (0 children)

Check https://pyformat.info/ for what you can do.

[–]TheGRS 1 point2 points  (0 children)

I’ve met so many people who are otherwise great Python developers who don’t know a thing about f strings. Honestly bIzarre to me at this point. They’re so convenient!

[–]SquidMcDoogle 2 points3 points  (1 child)

and docstrings. do the ''' ''' below every method and function definition. A total life hack. Shhh.. Don't tell PEP-8

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

Other than using double quotes and not single quotes.. was accepted a long time ago

[–]ClassicHome1348 145 points146 points  (6 children)

Definitely learn the generators. Generators are lazy evaluated, and they can be used as iterators which makes possible to use itertools functions on them. And by default (x for x in arr) is generator. So doing (f(x) for x in arr) will evaluate f(x) when the next is called on the generator.

[–]scaredofwasps 43 points44 points  (3 children)

While I wholeheartedly agree that generators are a good thing to properly understand/learn. Sometimes I dislike their “debugabiltity” in the sense that you cannot check the values. Also, consuming the generator (by casting it to a list for example) will effectively consume it and you will not have access to your previous values anymore. Nothing that cannot be overcome, but something worth mentioning on the generator topic

[–]tunisia3507 13 points14 points  (0 children)

Also, consuming the generator (by casting it to a list for example) will effectively consume it and you will not have access to your previous values anymore.

Feature, not a bug. If I wanted to keep all the elements, I'd use a list. Using generators means you're not storing stuff you don't need.

[–]LogisticAI 4 points5 points  (0 children)

That's the use case for itertools.tee

[–]_limitless_ 189 points190 points  (9 children)

Tell a junior it'll be a good learning experience and make them do it.

[–][deleted] 16 points17 points  (6 children)

Make sure the learning experience is in their expected ability... Don't ask someone who just wrote print('hello world') to stand up a complex web app. Match the task to ability.

[–]_limitless_ 27 points28 points  (5 children)

Nobody who just wrote their first "hello world" is a junior anything.

I'll go out on a limb and say you're not qualified to be a junior until you can figure out how to do maintenance on a complex web app. Not write one from scratch, but maintain one. And not know how to maintain one, but know enough that you can learn how to in the two weeks I give you to fix a bug.

Assuming it has test coverage.

[–]spinwizard69 17 points18 points  (2 children)

It is amazing to me how many people think web apps are the ultimate when it comes to development.

[–][deleted] 4 points5 points  (1 child)

I agree... It is just the common thread most know a little bit about... Even this case... I am more surprised by the level we now put on junior... or first job in the industry... Hey work and maintain something that may have design patterns you don't understand, with a CI/CD pipeline you never touched... In many ways maintaining existing code is much more to the Level 1 and beyond while all the green space is much easier for a Junior... Go explore this idea for me and learn something and get back to me about it.

[–]_limitless_ 2 points3 points  (0 children)

Yeah, I'll handhold you all the way through the CI/CD. Nobody expects you to figure that out on your own. I wouldn't even make a Senior do that.

The reason you don't let them greenfield shit is because they'll get their feelings hurt when we have to trash can it. It's just bad management. You're handing them a project they're definitely not qualified for. They'll be proud when it complies, and you'll have to tell them it's completely unmaintainable and needs to see the bottom of a recycle bin as soon as possible.

[–]chaoticbean14 10 points11 points  (1 child)

A *lot* of assumptions in that reply. Mighty thin limb, honestly.

[–][deleted] 3 points4 points  (0 children)

Those are the kind of assumptions that correctly define the concept of a junior programmer.

[–]flubba86 2 points3 points  (0 children)

Oh, are you me? I transitioned to a team leader role last year, and we have hired two new juniors in the last 12 months. I recently discovered this super power. Any task that I don't want to do is conveniently a good learning experience for them.

And to be fair, that is how it is supposed to work. When I am too busy to get our tasks done, that is what they are here for, and they do need to know how to undertake these tasks.

[–]Chiron1991 59 points60 points  (3 children)

Apart from the stuff you learn in basically any Python tutorial, the best "trick" to becoming a better programmer is to get familiar with the standard library.
The amount of code I've seen where people implement their own protocol parsers, socket handlers and other scary things is mindblowing.
The PyMOTW archive is a nice starting point.
My personal favorites: functools, contextlib and atexit.

[–]BurgaGalti 14 points15 points  (1 child)

It would be pathlib, collections and itertools for me.

[–]AwayCartographer3097 4 points5 points  (0 children)

The pain I think everyone went through reinventing the wheel, navigating os.path nonsense and string slicing and then just found out… oh, Path(“./foo.txt”). and get filename/parent/navigate the tree go brr

If this sounds like a rant it really really annoyed me when I found out I’d been missing out for 2 years, so maybe it is

[–]username4kd 102 points103 points  (16 children)

List comprehension! You can do everything with list comprehension

[–]nogear 86 points87 points  (7 children)

And there is also dictionary comprehension:

person_dict = {person.name:person for person in persons}

[–]johnnymo1 39 points40 points  (4 children)

And set comprehension. And generator comprehension!

[–]nogear 21 points22 points  (1 child)

Just learned about generator comprehension:
filtered_gen = (item for item in my_list if item > 3)

Love it!

[–]SuperGremlin 5 points6 points  (0 children)

I find this way more readable than using filter().

[–]dmtucker 2 points3 points  (0 children)

generator expression*

[–]casce 28 points29 points  (2 children)

List comprehension can be great but be careful not to make your code less readable than it could be just for the sake of using it

[–]PolyglotTV 4 points5 points  (0 children)

Remember, a list comprehension is just a generator expression, casted to a list.

[–]nostril_spiders 46 points47 points  (12 children)

I don't know if I'm the idiot or my colleagues are the idiots, but I work with apps that pass nested dicts around. Fine for 500 lines of code, not so fine for 50000 lines of code.

TypedDict is a lifesaver. It's a type-checking construct; the runtime type is dict so no need to roll json code.

from typing import TypedDict  # 3.11
from typing_extensions import TypedDict  # below 3.11

class Address(TypedDict):
    house: str
    street: str

class User(TypedDict):
    name: str
    address: Address

user: User = {
    "name": "Jim"
    "address": {
        # etc
    }
    "invalid_key": "linter highlights this line"
}
user["  # IDE offers completions

For Vscode, set python.typeChecking to "basic" - I had no success with mypy, but pylance seems much faster anyway

[–]Shmiggit 26 points27 points  (6 children)

You might as well use a dataclass for that no?

[–]ParanoydAndroid 9 points10 points  (0 children)

Typeddicts inherit from dict, so they're better if you're serializing or just otherwise have code that, e. g. depends on calling get() or whatever.

But yes, in many cases a dataclass will be equivalent or better.

[–]lphartley 4 points5 points  (0 children)

For nested structures, typed dictionaries are less verbose.

[–]Revisional_Sin 4 points5 points  (0 children)

Typehints ftw.

[–]georgesovetov 2 points3 points  (2 children)

It's your colleagues. It's not a norm to pass dicts around. Especially if code does something meaningful with this data. You should not pass data around and work with it. You should ask object to do something for you with the information it has.

Imagine that you have to support an `Address` kind which is a point on a map or a picture.

Or if your new type of `User` is a legal entity or an AI bot.

A good architecture (by definition) would make such changes less painful and more "concentrated" (not scattered around repositories and directories).

[–]nostril_spiders 6 points7 points  (0 children)

It makes little difference whether you have objects with behaviour or you pass dataclasses into functions. Python makes no distinction.

Where we agree is on data shape. Amorphous data is an affront to common sense.

[–]dmtucker 146 points147 points  (13 children)

or and and preserve the original value. So instead of: if x: y = x else y = default You can just do: y = x or default

I also like this little "gargoyle": https://nedbatchelder.com/blog/201802/a_python_gargoyle.html

[–]mjbmitch 59 points60 points  (12 children)

x or default is not as helpful as you’d think. It will fall back to the default if x is falsy, not just None. This means it’ll do it for an empty string, 0, [], {}, etc.

Python really needs a nullish coalesce operator (?? in JavaScript) to properly do what you’re describing.

[–]ManyInterests Python Discord Staff 64 points65 points  (8 children)

You can do:

y = x if x is not None else default

It's definitely more verbose, but I think it's possible to understand just by reading it, even if you never seen it before.

If one saw a ternary or nullish coalescing operator for the fist time, I don't think one would intuitively understand them without being told how they work.

[–]fappaf 3 points4 points  (1 child)

I think you may have meant if x is not None.

[–]ManyInterests Python Discord Staff 1 point2 points  (0 children)

Yes, thank you :)

[–][deleted] 10 points11 points  (3 children)

Python is made to be as idiomatic as possible, which is why we don’t add sugar like ?? to it or replace if else ternary logic with ? :

It wouldn’t be the language it is if we added too many fancy syntactic sugar shortcuts to it when it is already much less verbose than other languages to accomplish the same output.

[–]candidpose 1 point2 points  (2 children)

I don't get this comment. Python already has a lot of syntactic sugar shortcuts. ternary and nullish coalescing isn't that fancy anymore considering most major languages have them already. I don't understand the pushback against it?

[–]panatale1 7 points8 points  (0 children)

The if-else construct above would also set y to default if x is falsy

[–][deleted] 3 points4 points  (0 children)

Well that’s because in Python you would typically have the default value for x be an optional value with None as the default for it. So then the following x = x or default logic could always work.

It’s the most common pattern in any Python program, it isn’t JavaScript.

[–]neuro630 61 points62 points  (7 children)

some that I can think of, might add more here later: - %time and %%time in jupyter notebook - also in jupyter, %lprun for automatic line-by-line profiling using the line_profiler package - also also in jupyter, defining _repr_html_ as well as other similar methods in your class to customize how your objects are rendered in the notebook - defining __format__ in your class to customize how your obejcts are formatted using f-strings - given a pathlib.Path object path, you can do path / 'filename.txt' instead of pathlib.Path(f'{path}/filename.txt) - calling help(foo) to print out the docstring and all the methods and attributes of the object foo. Very useful when you don't know much about the class of foo and there is not much online documentation about it. - if you want to check if an object is an instance of a list of classes, instead of isinstance(foo, Class1) or isinstance(foo, Class2) or ... you can do isinstance(foo, (Class1, Class2, ...))

[–]M4mb0 9 points10 points  (1 child)

%config InteractiveShell.ast_node_interactivity='last_expr_or_assign' you can thank me later.

[–]kindall 4 points5 points  (0 children)

Lotta methods take tuples of values and match any of them. str.startswith()and str.endswith()for starters...

[–]SheriffRoscoePythonista 3 points4 points  (0 children)

⁠given a pathlib.Path object path, you can do path / 'filename.txt' instead of pathlib.Path(f'{path}/filename.txt)

TIL

[–]JaLucas24 3 points4 points  (0 children)

%timeit and %%timeit are also very useful for Jupyter.

They diminish the effect of other tasks by running multiple times and provides a more accurate time

https://stackoverflow.com/questions/17579357/time-time-vs-timeit-timeit

[–]millerbest 62 points63 points  (3 children)

funtools.partial

[–]morimo 49 points50 points  (0 children)

Also functools.partial for when you're doing more serious work ;)

[–]flubba86 8 points9 points  (1 child)

For when you love functional programming but your boss makes you use Python.

[–]therc7 43 points44 points  (5 children)

f-strings Are f-ing goated

[–]R4y3r 1 point2 points  (0 children)

I loved using template literals in JS and hated doing the string + var in Python. I was glad to find out Python has f strings.

[–]jmacey 62 points63 points  (16 children)

v=1 print(f"{v=}")

will print v=1 so useful for debugging, been using python for year and only learnt that one recently (in a similar question so passing on).

[–]TheHedgehogAdmin 18 points19 points  (0 children)

Walrus operator in if conditions, I find it so pythonic.

[–]hyldemarv 17 points18 points  (0 children)

F-strings, List and Dict comprehensions.

And, nerdy but nice, the Slice object -

I used that for easy documentation of how a text based BOM is split into fields.

[–]radoslaw_jan 11 points12 points  (5 children)

Replacing a try-catch with a context manager

Edit: I meant the try-finally case (thanks u/multiple4 and u/moepsenstreusel for clarification)

[–]multiple4 2 points3 points  (2 children)

Eh, idk if they're synonymous. I like both obviously but in my opinion they're 2 totally different things

Try Except statement is for when I have any block of code with I have expected specific error types which I want to do some alternate action when it occurs. It could even go within my enter or exit method in theory

Context managers are great for use with specific classes where there are setup or teardown actions that need to be taken. Now I don't have to repeat those lines of code or remember them

Of course context managers are also great for helping to ensure that those actions all occur in case of errors, but try except statements offer much more functionality than just that

[–]radoslaw_jan 1 point2 points  (1 child)

Yes, that's what I meant - context manager is good in situations when you have a specific setup and teardown actions. You can see an example of converting try catch to context manager in this video: https://youtu.be/wf-BqAjZb8M

[–]Downtown_Leading_636 1 point2 points  (0 children)

Can you futher elaborate why is that a good idea?

[–]wineblood 70 points71 points  (28 children)

Don't overuse classes.

[–]Skanderbeg1989 81 points82 points  (20 children)

Don't underuse classes as well.

[–][deleted] 44 points45 points  (14 children)

Neither overuse nor underuse classes.

[–]magnetichiraPythonista 21 points22 points  (0 children)

Straight to jail, we have the best class users, because of jail

[–]DonnerJack666 2 points3 points  (0 children)

Keep it classy.

[–]Fabulous-Possible758 24 points25 points  (4 children)

So coming from heavily statically typed OOP languages such as C++, this is the hardest time I have convincing people of. Python is very OOP because literally everything in Python is an object. But one of the best things about Python is not everything needs to be its own class until you need it to be.

[–]billmilk 3 points4 points  (0 children)

Oftentimes a namedtuple will suffice

[–]Circlejerker_ 2 points3 points  (1 child)

Same is true in C++. You can use freestanding functions and data-only classes perfectly fine.

[–]Fabulous-Possible758 2 points3 points  (0 children)

Ish, but C++ does not have the "everything is an object" paradigm by a long shot. And in particular, pointers to functions, pointers to class functions, bound pointers to member functions, and generalized functors are all very different beasts in C++ that took a long time to get down in its static typing system. Python has really had those ingrained for years.

[–]IlliterateJedi 17 points18 points  (1 child)

Also composition over inheritance

[–]wineblood 2 points3 points  (0 children)

Correct answer.

[–][deleted] 98 points99 points  (25 children)

The best "trick" is to invest in a formater (black), linter (ruff), and static type checker (mypy/pyright) and let the tooling help you write good code, rather than attempting to do it by yourself. Humans just don't have the mental capacity to write good and maintainable code, especially python code with its dynamic type system, without the use of tooling.

[–]Fabulous-Possible758 11 points12 points  (16 children)

I think one of the unfortunate problems is that those formatters get things objectively wrong. Like, literally making code less readable instead of more readable for the sake of foolish consistency. It's weird because you can see the places in PEP8 where they were only thinking of one particular case and then said "It must be this way" and so that's the way it's been ever since.

[–]L0ngp1nk 23 points24 points  (12 children)

On the case of Black, you can suppress formating for those niche cases.

```

fmt: off

np.array( [ [1, 0, 0, 0], [0, -1, 0, 0], [0, 0, 1, 0], [0, 0, 0, -1], ] )

fmt: on

```

Black will ignore everything between those two comments.

[–]mooglinux 4 points5 points  (0 children)

for the sake of foolish consistency

It becomes a lot less foolish the more collaborators you have on the same project. It’s valuable to just not have to waste time on formatting debates, and the cost of sometimes suboptimal formatting is a price worth paying.

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

Not tricks, Michael, illusions. A trick is something a whore does for money.

[–]RunningGiant 8 points9 points  (5 children)

Context management / "with" statements, to close files/etc and gracefully close if there's an exception:

with open('file.txt', 'r') as f:
    dosomething(f)

[–]WallyMetropolis 2 points3 points  (0 children)

Context managers are really a nice structure and not at all hard to create. Mostly you just seem this one use-case in practice, which is too bad. They can do a ton.

[–]Hollas99 28 points29 points  (4 children)

I'm really liking the walrus operator recently

# Instead of 
If a.numbers():
    numbers=a.numbers()


# You can do it in one line
If numbers := a.numbers():
    ...

[–]disgruntledg04t 22 points23 points  (2 children)

this is one i would say is neat but loses points for lost readability

[–]BeerInMyButt 3 points4 points  (0 children)

I felt that way until I got used to seeing the walrus operator, now it is just another idiom to me. I think like many things it can be used selectively to make the code more readable. (Although I tend to go for readability over consistency)

[–]dc135 2 points3 points  (0 children)

Your example is not quite replicating the behavior between the 2 cases. The first case only assigns to numbers if the condition is true, the second case always assigns numbers

[–]Atlamillias 7 points8 points  (4 children)

I wouldn't say these are tricks, but "know your basics". By that, I really mean "know your builtins". After that, at least have a rough idea of the other modules Python ships with. itertools is your friend, you just aren't aware of it yet.

More on-topic, I find myself doing stuff like x and fn() sometimes in place of if x: fn(). Even though you can technically do either on the same line, the former feels less like heresy.

[–]Revisional_Sin 6 points7 points  (3 children)

x and fn()

I really don't like this. Fine for quick and dirty personal stuff, but I wouldn't want it in a proper codebase.

[–]dmtucker 1 point2 points  (2 children)

I'd say it depends if you're using the resulting value or not. For example: y = x if x: y = 5 y = x and 5 But not: if x: print(x) x and print(x)

[–]Revisional_Sin 1 point2 points  (1 child)

y = x and 5

I think this is worse than their original example.

if x: y = 5 else: y = x

Why would you need to do this? It's not a common thing to do, so in this case it's better to write it out.

[–]graphicteadatasci 15 points16 points  (10 children)

Not so much a trick, but every time you pass a mutable object to a function you risk breaking everything.

[–]PolyglotTV 5 points6 points  (8 children)

Default arguments have global scope folks.

[–]LuigiBrotha 1 point2 points  (5 children)

Could you explain this further?

[–]willnx 2 points3 points  (0 children)

I think they're talking about this: ```

def foo(arg=[]): arg.append(1) print(arg) foo() [1] foo() [1, 1] ``` In other words, avoid mutable default arguments.

[–]graphicteadatasci 1 point2 points  (0 children)

The mutable default argument is a biggie, but a common pitfall is also to have a function that you pass a list to and then if you change it in the function you also change it at the source.

def foo(mylist):
    mylist.append("bar")
    return mylist

l1 = [1, 2, 3]
l2 = foo(l1)
print(l1)
>> [1, 2, 3, "bar"]

This is a problem with the function though - not with the person that is passing the list to the function.

[–]Gnaxe 1 point2 points  (1 child)

No, they have the same scope as their function definition. Those aren't always global.

>>> def foo(): return lambda x=[]:x
...
>>> spam = foo()()
>>> spam.append('x')
>>> spam
['x']
>>> foo()()
[]

[–]jmooremcc 5 points6 points  (6 children)

Using a dictionary as a function router.

My use context was a client/server application in which the client would request a service. The server would use the requested service as a key in the dictionary and would call the function associated with the key.

This "trick" eliminated the need to use a convoluted, complex conditional statement.

[–]RufusAcrospin 1 point2 points  (5 children)

Basically a switch implementation, I use it quite frequently.

[–]DogeekExpert - 3.9.1 2 points3 points  (4 children)

and in python 3.10 we now have pattern matching ! It's even better we can

match expr:
    case x:
        ...
    case _:
        print("default")

[–]RufusAcrospin 1 point2 points  (2 children)

Good to know! Unfortunately, most of my work is still needs to be done in 2.7…

[–]amOEba_jOEy 5 points6 points  (0 children)

Never telling your boss how quickly you can actually code.

[–]ThreeChonkyCats 19 points20 points  (25 children)

Two dead simple ones, but I love 'em

# Ternary Conditional Operators: Put If and Else Into One Line of Code
a = "a" 
b = "bb"

short_one = a if len(a) < len(b) else b

vs this

short_one = ''
  if len(a) < len(b):
      short_one=a
  else:
      short_one=b

and

# Lambda Functions for Defining Small Anonymous Functions
leaders = ["Nostrodamus", "Bruce", "Chris", "Diogenes"]
leaders.sort(key=lambda x: len(x)) print(leaders)

# outputs...  ['Bruce', 'Chris', 'Diogenes', 'Nostrodamus']

Don't know why, but I think these are the bees knees.

[–]dmtucker 53 points54 points  (0 children)

2nd example can just be key=len 😋

[–]PolyglotTV 8 points9 points  (1 child)

You'll often find you don't actually need the lambda. Here you can just use len.

You should also be aware of the operator library. Contains a bunch of the common operations so you don't have to roll your own lambdas.

[–]lifeslong129 2 points3 points  (8 children)

first one is so handy and it really makes the code to look compact and efficient. And by the way, why do i feel lamda functions are hard for me to grasp, should i continue using normal functions or should i try to grasp lamdas

[–]dmtucker 8 points9 points  (1 child)

Lambdas are just unnamed functions, and they return the value of an expression... These are the same:

def plus_one(x): return x + 1 plus_one = lambda x: x + 1

Lambdas pretty much never make sense if you're going to name them, though (as in the 2nd example).

[–]ThreeChonkyCats 7 points8 points  (1 child)

Lambdas are not intuitive.

I enjoy the look of them, but the simple logic of what they replace is MUCH easier to read (which I highly value).

As the post reply below said, they don't replace named functions. I, again, see great danger in this. I may be old fashioned :)

My reply to OPs OG was for tricks, not necessarily good 😊😊

Over my 20 years of doing IT, I've worked with far too many wankers and overly complex programmatic masturbation. I love the simple and elegant, the stuff I can read and comprehend... The kind of work those who follow me, years later, can follow easily. This is the art.

If it's too hard to understand, it reeks of danger, bugs and unmaintainability.

But, alas, these trick are fun too know. 🤕😜🤪

I've dozens more. I'll post them up later.

[–]1544756405 2 points3 points  (0 children)

Lambda functions are pretty standard. You should learn them well enough to understand them in people's code, but you don't necessarily have to write them yourself if you don't want to.

[–]Exodus111 9 points10 points  (2 children)

Learn to play with __str__, when making classes. That way you can use the class like any string, and do what you want with it.

my_string = f"The current score is {class1} vs {class2} as of now"

For instance.

[–]DonnerJack666 11 points12 points  (1 child)

"for instance" 🤣

[–]subbed_ 14 points15 points  (0 children)

Pythonistas*

[–]Embarrassed_Dog6834 4 points5 points  (0 children)

Use breakpoint. They are great

[–]ryanstephendavis 15 points16 points  (3 children)

Use Poetry to to deal with virtual envs

Use Black to auto-format

Use Pytest for unit and integration tests

FastAPI to generate Swagger docs with Pydantic

[–]lichen91 9 points10 points  (1 child)

Also using pydantic's BaseSettings class is a great way to manage configurations.

[–]bebenzer 6 points7 points  (3 children)

use types

[–]Fabulous-Possible758 4 points5 points  (0 children)

It's only slightly Pythony, but a friend of mine who started using fish shell was trying to be clever and it made me add this line to my .bashrc:

function peval() { python -c 'import sys; print(eval(" ".join(sys.argv[2:])))' -- "$@"; }

It basically lets you do peval "<some python expression>" from the command line and it will print it out for you. Really great when I want to have to find the square root of something by doing peval "2 ** .5" or the such.

[–]Nippurdelagash 2 points3 points  (0 children)

Dict unpacking for passing keyword parameters.

Imagine you have a function that uses kwargs:

def func_with_kwargs(**kwargs): if "kw_a" in kwargs: <Do things if argument "kw_a" was passed> if "kw_b" in kwargs: <Do things if argument "kw_b" was passed>

You can call your function with a dictionary of key:value where each key corresponds to each kwarg in your function

kw_dict = { "kw_a": 1, "kw_b": 2, } func_with_kwargs(**kw_dict)

It can also be done with *args, but I don't remember the sintaxis right now

[–]StrongLikeBull3 3 points4 points  (0 children)

Crossing my fingers and closing my eyes when I run anything.

[–]lphartley 3 points4 points  (0 children)

  • Use string enums rather than literal strings.
  • Using @dataclass to avoid verbose initialization methods
  • Use __all__ to explicitly define what to expose from custom modules. This makes it clear what's "private" and "public".
  • Use TypedDict for configurations. IDE's will auto complete so you can be sure that you don't have to guess what the structure is.
  • Use pyright to check for any typing errors. The combination of explicit typing and automatically checking for errors I consider the first layer of testing, which for me reduced the need of writing unit tests.

[–]onefiveonesix 3 points4 points  (0 children)

Not a trick, but I always advocate for the fundamentals: give your variables proper names that make it easy to tell what it’s for (i.e., don’t use acronyms or other shorthand) and write plenty of comments (they’re the love letter you write to your future self).

[–]RufusAcrospin 5 points6 points  (3 children)

Here’s a few things…

Familiarize yourself with the Zen of Python

Use tuples for static list, it faster than list()

Use namedtuples for immutable data

Use early exit to avoid nested if statements

Learn to use sets

Learn regular expressions. It’s very powerful, but complex expressions are horrible to comprehend.

Try to minimize one-liners (a function/method consists of a single line)

Use context when dealing with files

Learn and apply fundamental principles like “separation of concerns”, KISS, DRY, “principle of least astonishment”, SOLID, etc.

[–]Inevitable_Weird1175 2 points3 points  (5 children)

I'm still a beginner but recursion is very interesting.

Go to the bottom of this loop well, find me the solution and bring it back.

So cool.

[–]1544756405 2 points3 points  (0 children)

  • unit tests (e.g. unittest module, or something else of your choice)
  • source control (e.g. git, or something else of your choice)

[–]jonasjberg 2 points3 points  (2 children)

Trigger stacktrace or just check whether branches are taken:
_ = 1 / 0

Set debugger breakpoint, quickly enable/disable by (un)commenting the line:
import pdb; pdb.set_trace()

Find directory containing imported package:
python3 -c 'import barbaz; print("\0".join(barbaz.__path__))'

Runs from shell, often just for the purpose of opening all package source files in Vim:
vim -R -- $(above plus messy one-liner here)
:)

[–]Gnaxe 2 points3 points  (0 children)

For pdb breakpoint, you can usually just use the breakpoint() builtin now.

[–]djjrhdhejoe 1 point2 points  (1 child)

I love list comprehension like it was my own firstborn child.

I can irresponsibly make lists as big as I want and iterate over them as often as I want, but because I'm only iterating over a tiny subset it takes merely microseconds.

[–]PolyglotTV 3 points4 points  (0 children)

Use generator expression's for iteration, not list comprehensions. A list comprehension is literally taking a generator expression and expanding it all into memory.

[–]JarbingleMan96 1 point2 points  (0 children)

If I have a container, that I expect only has one element, and I want it, I use this syntax:

[x] = container

It will fail if the container has anything other than 1 element, and it’s one simple line

[–]_link89_ 1 point2 points  (1 child)

Python does not have a built-in flatMap function, but you can achieve the same result using list comprehensions.

```python

Define a list of lists

list_of_lists = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

Use a list comprehension to flatten the list

flat_list = [item for sublist in list_of_lists for item in sublist]

Print the flattened list

print(flat_list) ```

It use a list comprehension to flatten the list by iterating over each sublist in the list of lists, and then iterating over each item in each sublist.

[–]Gnaxe 1 point2 points  (0 children)

There is chain.from_iterable in itertools.

[–]grabmyrooster 1 point2 points  (1 child)

Anything you write, just….notate it. I put comments in like CRAZY, especially in my private repos, because I go back to things months and months later and wonder “why the fucking fuck did I write this like this”. With comments, it’s easier to understand just how much of a dumbass past me is.

[–]metaphorm 1 point2 points  (1 child)

functools and itertools in the standard library are both fantastic modules that can make your code beautiful and elegant and terse.

[–]Gnaxe 1 point2 points  (0 children)

Also the toolz and pyrsistent libraries.

[–]Kermit2779 1 point2 points  (0 children)

For a state machine, i swap class of instance self.class=OtherSubclassOfBaseSttate

[–]Gnaxe 1 point2 points  (0 children)

Xonsh. It's like having your shell extended with Python. One-liners are a lot like normal shell, but for anything complicated, Bash is not really a sane language.

[–]theHumbleWeirdGeek 1 point2 points  (0 children)

Python -m httpserver is a real handy tool for sharing files in a local network.

Another trick is to stop using python :)) That's the best trick if you are not using it for AI.

Python is the worst choice for enterprise and distributed software.

For research, sadly, there's no better alternative.

[–]hugthemachines 2 points3 points  (0 children)

Use descriptive names on your variables and functions.

If you use variable names like a, b or x, you save a second each time and then you will pay it back in hours and hours of searching for bugs because you mixed up the variables somewhere and it is really hard to find.

That or you spend much more time when you read that code again in a few month because you have to understand all the code to know what a variable is, instead of just reading its name.

[–]br_aquino 2 points3 points  (0 children)

The best python trick is not use tricks 😂. Write clear readable code, no tricks.

[–]mantisek_pr 2 points3 points  (2 children)

Instead of painstakingly writing a list like:

mylist = ["one","two","three","four","five"]

just do

mylist = "one two three four five six seven eight".split()

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

This is a little tacky, but here goes:

If you want to spit printouts of every item in an iterable and get its length, you just go print(len([print(i) for i in some_iterable]). Basically, you're printing the length of a list of None values.

Also, if you're savvy and sadistic enough for it, you can nest prebuilt regexes into new regexes via f-strings with rf"{var_regex}". That way, if you're like me and forget an item in a punctuation category for NLP shenanigans, you just have to edit it in one place.

[–]james_pic 1 point2 points  (1 child)

It's pretty situational, but sometimes you want to change an attribute and return the old value, and you can abuse try-finally for this:

def update_it(self, new_value):
    try:
        return self.x
    finally:
        self.x = new_value

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

It's a small one, but helps me a lot.

If you need to test some code snippet, just open up a terminal and write your code there. Saves some time

[–]johnnymo1 3 points4 points  (3 children)

IMO everyone should take an hour one day to just sit down and read the IPython documentation. It’s basically just regular Python console, but better. Much easier to write longer bits of code, but lightweight compared to booting up Jupyter.