1
32
Python 3.13.7 (www.python.org)
2
40
3
23
4
9
5
9
6
19
7
26
8
56

A hard exercise to help build the right mental model for Python data.

The “Solution” link visualizes execution and reveals what’s actually happening using 𝗺𝗲𝗺𝗼𝗿𝘆_𝗴𝗿𝗮𝗽𝗵: https://github.com/bterwijn/memory_graph

9
25
10
4
11
3
12
10
13
16
14
19
15
12
submitted 1 month ago by cm0002@mander.xyz to c/python@programming.dev
16
12

In last week’s post we showed that a Python for-loop works through the Iterator Protocol.

This same protocol also enables values to be produced lazily.

In this new Lazy Evalution Example we show one sink reading values from five different sources:

  • source1: eagerly returns all values by list
  • source2: lazily by generator function using yield
  • source3: eagerly by list comprehension
  • source4: lazily by generator expression
  • source5: lazily by iterator protocol

The same for-loop consumes all five sources. The eager sources produce all values before the sink starts consuming them. In the lazy sources producer and consumer take turns:

  • produce → consume → produce → consume → …

Each value is produced only when the for-loop requests it.

Generator functions and generator expressions are concise, readable ways to create lazy iterables. The final source makes their underlying mechanism explicit:

  • iter() obtains an iterator.
  • next() requests the next value.
  • StopIteration signals that no values remain.

This clearly shows that generators achieve lazy iteration by implementing Python’s Iterator Protocol.

17
9
IPython is All You Need (nathancooper.io)

"I use IPython as my terminal's shell."

"IPython in the shell?"

"No, IPython is the shell."

"IPython? As the shell?"

"Only way to live."

18
50
19
11
20
-4
21
13
submitted 1 month ago* (last edited 1 month ago) by bterwijn@programming.dev to c/python@programming.dev

Yesterday my exercise got downvoted, probably because its point was unclear. I'd like to try again with this reworked exercise. Hope you'll like this one better.

  • Solution
  • Explanation: “User-defined classes have __eq__() and __hash__() methods by default (inherited from the object class); with them, all objects compare unequal (except with themselves) and x.__hash__() returns an appropriate value such that x == y implies both that x is y and hash(x) == hash(y).”

#Python #memory_graph #Equality #Hashing

22
10
23
-5

An exercise to help build the right mental model for Python data.

  • Solution
  • Explanation: "User-defined classes have __eq__() and __hash__() methods by default (inherited from the object class); with them, all objects compare unequal (except with themselves) and x.__hash__() returns an appropriate value such that x == y implies both that x is y and hash(x) == hash(y)."

#Python #memory_graph #Equality #Hashing

24
21
submitted 1 month ago* (last edited 1 month ago) by marmelab@programming.dev to c/python@programming.dev

So I recently inherited a legacy application that was a nightmare to maintain (tooling was clearly lacking and the codebase was pretty outdated). I quickly realized that if I ever wanted to actually enjoy working on it, I would have to give it a proper overhaul.

These are the 5 changes that had some of the biggest impact IMO:

  1. uv: Being new to the Python ecosystem, I didn't want to figure out pip vs poetry vs pyenv vs virtualenv, so I just used uv and let it handle all of that. One Rust-based tool that installs and pins Python versions, manages the venv automatically and locks deps in a uv.lock for reproducible builds. Installs are also a lot faster, which makes CI a lot less painful.

  2. Ruff:

Coming from JS, I really missed eslint --fix for automatically fixing linting issues and format code on save. Ruff brought that experience back. I know that there are plenty of linters and formatters in the Python ecosystem, but this one really stands out for me. Since it's built in Rust, it's super fast.

  1. Dependabot:

Instead of remembering to update dependencies every few months, I enabled Dependabot. It automatically opens PRs when updates are available and then CI tells me whether they're safe to merge. It takes only a couple of minutes to set up but saves a lot of maintenance.

  1. Pylance:

Without it, VS Code gives generic completions and never warns you about passing the wrong type until runtime. Pylance provides proper type-aware autocompletion, jump-to-definition (even in third-party libraries), inline documentation, and real-time type checking. I personally keep it on "basic" mode for legacy codebases, since "strict" surfaced hundreds of errors (thank you, but no thank you lol).

  1. Pydantic:

Pydantic is basically Python's Zod: you declare a model, pass your data in and get either a validated typed object or a ValidationError naming the exact field at fault. It really helped me keep the codebase clean, with one place defining the shape of the data instead of raw dicts floating around. I use it wherever data comes from outside, like API payloads, forms, and env vars with pydantic-settings, which fails at startup instead of mid-request.

None of these tools changed the application itself. But together they made working on it a lot less frustrating.

25
16
submitted 2 months ago by nemeski@mander.xyz to c/python@programming.dev
view more: next ›

Python

8070 readers
4 users here now

Welcome to the Python community on the programming.dev Lemmy instance!

📅 Events

PastNovember 2023

October 2023

July 2023

August 2023

September 2023

🐍 Python project:
💓 Python Community:
✨ Python Ecosystem:
🌌 Fediverse
Communities
Projects
Feeds

founded 3 years ago
MODERATORS