🧠 Python doesn’t “free memory”. It negotiates with it. Most developers know that Python has Garbage Collection. Very few know how it actually works internally. Let’s break it down. 1. Reference Counting (Primary Memory Manager) At the core of Python’s memory management is reference counting. Every object in Python maintains a counter that tracks how many references point to it. Example: a = [1,2,3] b = a Now the list object has 2 references. Internally (in CPython): PyObject ├── ob_refcnt ← reference count └── ob_type Whenever a new reference is created → refcnt +1 Whenever a reference is deleted → refcnt -1 When the count hits 0, Python immediately deallocates the object. That’s why: a = [1,2,3] del a Memory is freed instantly. ⚡ This makes Python’s memory management very fast and deterministic. But there is a problem. 2. The Circular Reference Problem Reference counting cannot detect cycles. Example: a = [] b = [] a.append(b) b.append(a) Even if you delete both: del a del b Both objects still reference each other. So their reference count never reaches 0. Memory leak. This is where Python’s Garbage Collector comes in. 3. Generational Garbage Collector Python adds a cycle detector on top of reference counting. It uses a generational model. Objects are divided into 3 generations: Generation 0 → New objects Generation 1 → Survived one GC cycle Generation 2 → Long lived objects Why? Because most objects die young. This is called the Generational Hypothesis. So Python runs GC more frequently on young objects. Example thresholds: Gen0 threshold ≈ 700 allocations Gen1 threshold ≈ 10 Gen0 collections Gen2 threshold ≈ 10 Gen1 collections This keeps GC fast and efficient. 4. How Cycle Detection Works Internally Python uses a mark-and-sweep style algorithm. Steps: 1️⃣ Identify container objects (lists, dicts, classes) 2️⃣ Track references between them 3️⃣ Temporarily reduce reference counts 4️⃣ Objects that reach zero → unreachable cycle 5️⃣ Free them All of this is implemented in: Modules/gcmodule.c Inside CPython. 5. Interesting Internals You can actually inspect GC behavior: import gc gc.get_threshold() gc.get_count() gc.collect() You can even disable GC: gc.disable() Which some high-frequency trading systems and low latency apps do to avoid GC pauses. (Manual control > unpredictable pauses) 6. Why Python Rarely Leaks Memory Because it combines: ✔ Reference counting (instant cleanup) ✔ Generational GC (cycle detection) This hybrid model makes Python one of the most predictable memory managers among dynamic languages. Most developers use Python. Very few explore CPython internals. But once you understand things like: • PyObject • reference counters • generational GC You start seeing Python less like a language… and more like a beautifully engineered runtime system. #Python #CPython #GarbageCollection #Programming #PythonInternals #SoftwareEngineering
Python's Memory Management: Reference Counting and Garbage Collection
More Relevant Posts
-
🧙♂️ Magic Methods in Python (Dunder Methods) Python is known for its powerful and flexible object-oriented features. One of the most interesting concepts in Python is Magic Methods, also called Dunder Methods (Double Underscore Methods). Magic methods allow developers to define how objects behave with built-in operations such as addition, printing, comparison, and more. These methods always start and end with double underscores (__). Example: __init__ __str__ __add__ __len__ They are automatically called by Python when certain operations are performed. --- 🔹 Why Magic Methods are Important? Magic methods help to: ✔ Customize the behavior of objects ✔ Make classes behave like built-in types ✔ Improve code readability ✔ Implement operator overloading They allow developers to write clean, powerful, and Pythonic code. --- 🔹 Commonly Used Magic Methods 1️⃣ __init__ – Constructor This method is automatically called when an object is created. class Student: def __init__(self, name): self.name = name s = Student("Vamshi") --- 2️⃣ __str__ – String Representation Defines what should be displayed when we print the object. class Student: def __init__(self, name): self.name = name def __str__(self): return f"Student name is {self.name}" s = Student("Vamshi") print(s) --- 3️⃣ __len__ – Length of Object Allows objects to work with the len() function. class Team: def __init__(self, members): self.members = members def __len__(self): return len(self.members) t = Team(["A", "B", "C"]) print(len(t)) 4️⃣ __add__ – Operator Overloading Defines how the + operator works for objects. class Number: def __init__(self, value): self.value = value def __add__(self, other): return self.value + other.value n1 = Number(10) n2 = Number(20) print(n1 + n2) 🔹 Key Takeaway Magic methods make Python classes more powerful and flexible by allowing objects to interact naturally with Python's built-in operations. Understanding magic methods helps developers write cleaner and more advanced object-oriented programs. #Python #PythonProgramming #MagicMethods #DunderMethods #OOP #Coding #LearnPython #SoftwareDevelopment
To view or add a comment, sign in
-
-
🚀 DSA with Python – Bit Manipulation Practice Today I continued my Data Structures & Algorithms practice with Python, focusing on Bit Manipulation problems. For each problem, I first explored the brute force / generic approach and then implemented a more efficient solution using bitwise operations. Here are the concepts I practiced today 👇 🔹 1. Lonely Integer Problem: Given an array where every element appears twice except one, find the unique element. 💡 Key Bitwise Observations a ^ a = 0 a ^ 0 = a XOR is commutative and associative So when we XOR all elements, the duplicate numbers cancel each other and the unique element remains. Example: [5,1,4,4,5,3,1] → Lonely Integer = 3 Efficient idea: Iterate through the array and keep XORing elements. Time Complexity: O(n) 🔹 2. Longest Consecutive 1’s in Binary Goal: Find the maximum length of consecutive 1s in the binary representation of a number. 💡 Observation If we perform: n = n & (n << 1) Each iteration removes one consecutive layer of 1s The number of iterations equals the maximum consecutive 1s Example: n = 1101110 By repeatedly applying n & (n << 1), we count how many times it stays non-zero. Time Complexity: O(log n) 🔹 3. Swap Even and Odd Bits Swap every even-positioned bit with the adjacent odd-positioned bit. 💡 Approach 1️⃣ Extract even bits using mask 0xAAAAAAAA 2️⃣ Extract odd bits using mask 0x55555555 3️⃣ Shift them appropriately 4️⃣ Combine using OR Expression: ((n & 0xAAAAAAAA) >> 1) | ((n & 0x55555555) << 1) Time Complexity: O(1) Example: n = 181 Binary swap results in output: 122 🔹 4. Trailing Zeros in Binary Find the number of trailing zeros in the binary representation of a number. Example: n = 168 → 10101000 Trailing zeros = 3 💡 Observation Using the expression: (n ^ (n-1)) & n The result forms a power of two, and using log₂ we can determine the number of trailing zeros. 📚 Key Learning Bit manipulation helps in: ✔ Writing highly optimized solutions ✔ Reducing time complexity ✔ Solving many interview-level problems efficiently Practicing and documenting each concept step-by-step really helps in strengthening problem-solving skills. #DSA #Python #DataStructures #Algorithms #BitManipulation #BitwiseOperators #CodingPractice #ProblemSolving #SoftwareEngineering #PythonDeveloper #DeveloperJourney #InterviewPreparation #CodingInterview #LearnInPublic #BuildInPublic #TechLearning #Programming #ContinuousLearning #100DaysOfCode #DSA #Python #Algorithms #TimeComplexity #BigO #BackendDevelopment #SoftwareEngineering #ProblemSolving #CodingJourney #PythonDeveloper #BackendEngineer #SoftwareDeveloper #FullStackDeveloper #TechInterviews #CodingInterview #InterviewPreparation #ActivelyLooking #CareerGrowth #TechJobs #JobOpportunities #IndiaJobs #BangaloreJobs #HyderabadJobs #RemoteJobs #100DaysOfCode #ContinuousLearning #BuildInPublic #DeveloperJourney
To view or add a comment, sign in
-
-
Is your Python code hiding "silent killers"? Python is the industry standard for data science and AI development, but its impressive speed is powered by a hidden engine: C-extensions. Libraries like NumPy, TensorFlow, and SciPy rely on C to handle the heavy lifting. However, there’s a catch. When C code fails, it doesn’t just throw a Python Exception. It triggers a Segmentation Fault that kills the entire Python interpreter. This can be a real nightmare for developers building automated testing pipelines. To address this, fascinating new research on Fault Detection for C-Extended Python Projects evolved Pynguin, a well-known automated testing tool, to handle these fatal crashes head-on. 𝗧𝗵𝗲 𝗣𝗿𝗼𝗯𝗹𝗲𝗺: 𝗪𝗵𝗲𝗻 𝗧𝗲𝘀𝘁𝗶𝗻𝗴 𝗛𝗶𝘁𝘀 𝗮 𝗧𝗲𝗿𝗺𝗶𝗻𝗮𝗹 𝗪𝗮𝗹𝗹 Typically, Pynguin generates thousands of tests and runs them all in the same process. But if it runs into an edge-case input that causes a C-extension to SegFault, the crash takes down the testing tool itself. This means the test generation stops, leaving the rest of the codebase completely untested. 𝗧𝗵𝗲 𝗦𝗼𝗹𝘂𝘁𝗶𝗼𝗻: 𝗦𝘂𝗯𝗽𝗿𝗼𝗰𝗲𝘀𝘀 "𝗦𝗮𝗻𝗱𝗯𝗼𝘅𝗶𝗻𝗴" Researchers revamped Pynguin to utilize Subprocess-Execution. Instead of running tests in shared threads, the new version of Pynguin sends each test into its own isolated subprocess (a sandbox). If a C-extension faults, it only takes out the sandbox. The main testing tool continues to function, records the exact input that caused the crash, and moves on to the next test. 𝗧𝗵𝗲 𝗥𝗲𝘀𝘂𝗹𝘁𝘀 The researchers put this upgraded tool to the test on 1,648 modules across 21 large open-source libraries. Since the tool no longer self-destructs at the first fatal error, the results were astounding: • It successfully tested 56.5% more modules that were previously impossible to evaluate. • It automatically captured 213 unique crash causes. • It uncovered 32 zero-day bugs in major libraries that developers overlooked. If you’re building high-performance AI systems or backend infrastructure, check out the full research paper here to see how they pulled it off: tinyurl.com/3zvcupu9.
To view or add a comment, sign in
-
-
1: Everything is an object? In the world of Python, (an integer, a string, a list , or even a function) are all treated as an objects. This is what makes Python so flexible but introduces specific behaviors regarding memory management and data integrity that must be will known for each developer. 2: ID and type: Every object has 3 components: identity, type, and value. - Identity: The object's address in memory, it can be retrieved by using id() function. - Type: Defines what the object can do and what values could be hold. *a = [1, 2, 3] print(id(a)) print(type(a)) 3: Mutable Objects: Contents can be changed after they're created without changing their identity. E.x. lists, dictionaries, sets, and byte arrays. *l1 = [1, 2, 3] l2 = l1 l1.append(4) print(l2) 4: Immutable Objects: Once it is created, it can't be changed. If you try to modify it, Python create new object with a new identity. This includes integers, floats, strings, tuples, frozensets, and bytes. *s1 = "Holberton" s2 = s1 s1 = s1 + "school" print(s2) 5: why it matters? and how Python treats objects? The distinction between them dictates how Python manages memory. Python uses integer interning (pre-allocating small integers between -5 and 256) and string interning for performance. However, it is matter because aliasing (two variables pointing to the same object) can lead to bugs. Understanding this allows you to choose the right data structure. 6: Passing Arguments to Functions: "Call by Assignment." is a mechanism used by Python. When you pass an argument to a function, Python passes the reference to the object. - Mutable: If you pass a list to a function and modify it inside, the change persists outside because the function operated on the original memory address. - Immutable: If you pass a string and modify it inside, the function creates a local copy, leaving the original external variable untouched. *def increment(n, l): n += 1 l.append(1) val = 10 my_list = [10] increment(val, my_list) print(val) print(my_list) *: Indicates an examples. I didn't involve the output, you can try it!
To view or add a comment, sign in
-
-
Task Holberton Python: Mutable vs Immutable Objects During this trimester at Holberton, we started by learning the basics of the Python language. Then, as time went on, both the difficulty and our knowledge gradually increased. We also learned how to create and manipulate databases using SQL and NoSQL, what Server-Side Rendering is, how routing works, and many other things. This post will only show you a small part of everything we learned in Python during this trimester, as covering everything would be quite long. Enjoy your reading 🙂 Understanding how Python handles objects is essential for writing clean and predictable code. In Python, every value is an object with an identity (memory address), a type, and a value. Identity & Type x = 10 print(id(x)) print(type(x)) Mutable Objects Mutable objects (like lists, dicts, sets) can change without changing their identity. lst = [1, 2, 3] lst.append(4) print(lst) # [1, 2, 3, 4] Immutable Objects Immutable objects (like int, str, tuple) cannot be changed. Any modification creates a new object. x = 5 x = x + 1 # new object Why It Matters With mutable objects, changes affect all references: a = [1, 2] b = a b.append(3) print(a) # [1, 2, 3] With immutable objects, they don’t: a = "hi" b = a b += "!" print(a) # "hi" Function Arguments Python uses “pass by object reference”. Immutable example: def add_one(x): x += 1 n = 5 add_one(n) print(n) # 5 Mutable example: def add_item(lst): lst.append(4) l = [1, 2] add_item(l) print(l) # [1, 2, 4] Advanced Notes - Shallow vs deep copy matters for nested objects - Beware of aliasing: matrix = [[0]*3]*3 Conclusion Mutable objects can change in place, while immutable ones cannot. This impacts how Python handles variables, memory, and function arguments—key knowledge to avoid bugs.
To view or add a comment, sign in
-
Python for the Brain, .NET for the Nervous System. 🧠⚙️ Most AI models are born in Python, but the ones that survive at enterprise scale are increasingly running on .NET. While Python is the undisputed king of research and prototyping, it often hits a wall when it meets the brutal demands of a production environment. If you’re building high-performance, scalable, and mission-critical AI systems, here is why .NET (C#) is outshining the competition: 1. The Performance Gap (Compiled > Interpreted) Python is interpreted; .NET is JIT-compiled. In the world of real-time AI inference, every millisecond of latency matters. .NET’s native multithreading allows it to handle massive concurrent loads without being throttled by Python’s infamous Global Interpreter Lock (GIL). 2. Enterprise-Grade Reliability * Static Typing: Catch errors at compile-time, not at 3:00 AM in your production logs. * Memory Management: The Common Language Runtime (CLR) provides more efficient garbage collection, preventing the "latency spikes" that plague Python under heavy loads. * Security & Monitoring: .NET offers mature, built-in tools for authorization and API boundaries that are often an afterthought in Python POCs. 3. The "Hybrid" Winning Strategy 🏆 The best teams aren't choosing one over the other; they are using a split approach: * Python: Used as the "Experimental Brain" for training and model R&D. * ONNX Runtime & .NET: Used as the "Production Nervous System." By exporting models to ONNX, you get the best of both worlds—research flexibility and high-speed, type-safe execution. Why the shift to .NET for Production? * Execution Speed: High performance via Compiled/JIT execution vs. Python’s slower interpreted nature. * Concurrency: Excellent native threading capabilities, whereas Python remains bottlenecked by the GIL. * System Robustness: A static type system that ensures stability, compared to the dynamic prototyping focus of Python. * Scalability: Built specifically for the "Nervous System" of an enterprise, while Python excels as the "Experimental Brain." The Verdict: If you want to build a cool demo, use Python. If you want to build a resilient, multi-tenant AI platform that integrates seamlessly with the Azure ecosystem, it’s time to look at .NET. Are you moving AI into production this year? What’s your stack of choice? Let’s debate in the comments. 👇 #DotNet #CSharp #AI #SoftwareEngineering #MachineLearning #Azure #Python #TechArchitecture #ProductionAI
To view or add a comment, sign in
-
The Python GIL. The most misunderstood part of Python. Many developers say Python cannot do multithreading because of the Global Interpreter Lock. That statement is only partially true. To understand the GIL, we first need to understand how CPython executes code. CPython is not inherently thread safe. Many internal operations such as reference counting modify shared memory structures. If multiple threads modified these structures simultaneously, the interpreter could easily corrupt memory or crash. To prevent this, CPython uses a global mutex called the Global Interpreter Lock. The rule is simple. At any moment, only one thread is allowed to execute Python bytecode. Even if you create multiple threads using the threading module, they must take turns holding the GIL before executing Python instructions. This means CPU bound Python threads do not truly run in parallel. Example import threading def task(): for _ in range(10**7): pass t1 = threading.Thread(target=task) t2 = threading.Thread(target=task) t1.start() t2.start() t1.join() t2.join() Even though two threads are created, only one thread runs Python bytecode at a time because of the GIL. So why does Python still support threads? Because the GIL is released during blocking operations. When Python performs operations such as file reading, network requests, or database queries, the interpreter temporarily releases the GIL. This allows another thread to run while the first thread waits for the operating system. Example scenarios where threads work well Network requests File I O Database queries External API calls In these situations, Python threads can provide real concurrency because most of the time is spent waiting for external systems. Another interesting detail is how thread switching happens. CPython periodically forces a thread to release the GIL after executing a certain number of bytecode instructions. This mechanism prevents one thread from monopolizing the interpreter. In modern Python versions, the interpreter also checks time based intervals to decide when to switch threads. This gives other threads the chance to acquire the lock and continue execution. So the real impact of the GIL depends on the type of workload. CPU bound workloads such as heavy computation or numerical loops will not benefit from multithreading in CPython. I O bound workloads can still scale very well using threads. For CPU heavy workloads, developers usually rely on Multiprocessing which runs separate processes with separate interpreters Native extensions written in C that release the GIL Libraries like NumPy that perform computation outside the interpreter Interestingly, the GIL also simplifies CPython’s design. Because only one thread executes bytecode at a time, many internal data structures do not require complex locking mechanisms. This keeps the interpreter simpler and often faster for single threaded workloads.
To view or add a comment, sign in
-
-
🚀 Day 3 – Python Practice Progress( 6 of 50 questions solved) Problems I practiced today: ✔ Check if a number is even or odd ✔ Find the largest of three numbers ✔ Print numbers from 1 to N ✔ Find the sum of numbers from 1 to N ✔ Check if a number is prime ✔ Check if a string is a palindrome While solving these, I practiced using: • Conditional statements • Loops (while / for) • Input validation using try–except • String slicing (for palindrome checking) 💡 One interesting concept I explored today was Python slicing: s = "python" print(s[::-1]) This reverses the string because the step -1 makes Python traverse the sequence backwards. Small problems like these are helping me build stronger problem-solving skills in Python. Looking forward to practicing more tomorrow. #Python #DataScience #Programming 1 Check if a number is even or odd. try: num1=int(input("Enter a Number : ")) if num1%2==0: print("number is even") else: print("number is odd") except ValueError: print("invalid input. Please enter a number") 2. Find the largest of three numbers. try: num1=int(input("Enter first Number: ")) num2=int(input("Enter second Number: ")) num3=int(input("Enter third Number: ")) if num1>num2 and num2>num3: print("Larget Number is :", num1) elif num2>num3 and num2>num1: print("Largest Number is :", num2) else: print("Largest Number is :", num3) except ValueError: print("invalid Input. Please enter a number") 3 Print numbers from 1 to N try: num1=int(input("Enter a Number: ")) if num1>0: s=0 while s<=num1: print(s) s=s+1; else: p=0 while p>=num1: print(p) p=p-1; except ValueError: print("invalid input, please enter a number") 4 Find the sum of numbers from 1 to N. try: num=int(input("Enter a number : ")) if num>0: s=0 i=0 while i<=num: s=s+i; i=i+1; print(s) else: p=0 q=0 while q >=num: p=p+q; q=q-1; print(p) except ValueError: print("invalid input. Enter correct Number") Check if a number is prime. try: num=int(input("Enter a number : ")) if num>1: is_prime=True i=2 while i <num: if num%i==0: is_prime=False break i=i+1 if is_prime: print("Number is prime") else: print("Number is not prime") else: print("Enter a number greater than 1") except ValueError: print("Invalid Input. enter valid number") 6. Check if a string is a palindrome. try: num=str(input("Enter a sring:")) if num==num[::-1]: print("Palindrome") else: print("not a palindrome") except ValueError: print("invalid input. Enter a string")
To view or add a comment, sign in
-
*🚀Problem Solving with DSA - Day 47: Under the Hood | Internal Working of Python Dictionaries 🛠️🐍* ->Welcome to Day 47 of my 60-Day DSA Challenge! Today, we are cracking open the Python Dictionary to see how it achieves that lightning-fast O(1) speed. 🏗️ The Architecture: Buckets & Key-Value Pairs ->In Python, a dictionary is essentially a Hash Table. When you do my_dict["name"] = "Sriman", here is what happens: ->Hashing: Python calls the hash() function on your key ("name"). This generates a large integer. ->Indexing: It takes that integer and performs a modulo operation with the current size of the hash table: index = hash("name") % array_size. ->Storage: It stores the key, the hash value, and the actual value in a "Bucket" at that index. ⚔️ Collision Handling in Python: Open Addressing ->Unlike Java (which uses Chaining/Linked Lists), Python uses Open Addressing with a special probing technique. ->If a collision occurs (two keys map to the same index), Python doesn't create a list. ->Instead, it looks for another empty slot using a Pseudo-random Probing sequence. This keeps the data "flat" and cache-friendly. 📈 Dynamic Resizing: The Load Factor ->A HashMap works best when it's not too full. ->Load Factor: It’s the ratio of (number of items) / (table size). ->Resizing: When the dictionary gets about 2/3rd full, Python automatically creates a larger table (usually 2x or 4x the size) and re-hashes all existing keys into the new table. This ensures operations stay O(1). 💻 Python Code: Simulating the Logic # How Python sees your data key = "Day47" value = "HashMap Internal" # 1. Get Hash h = hash(key) # 2. Map to Index (Simplified) capacity = 8 index = h & (capacity - 1) # Efficient bitwise way to do modulo print(f"Key: {key} hashes to index: {index}") 📊 Python Dict Optimization (Compact Dict): ->Since Python 3.6+, dictionaries are ordered by default. They use a split-table design (an indices array and an entries array) which saves a lot of memory. 🧠 Challenge of the Day: ->"If Python uses Open Addressing, what happens to the search time if we keep adding elements without ever resizing the table? Why is the 2/3rd threshold important?" 📈 Progress Tracking: Current Topic: Dictionary Internals Status: Day 47/60 ✅ (78% Complete!) Next Up: Handling Collisions Understanding the 'Internal Magic' makes you a better developer, not just a coder mama! Ready to apply this speed to some real interview problems tomorrow? 👇 #60DaysOfCode #Python #HashMap #Hashing #SoftwareEngineering #InternalWorking #BigO #DataStructures #Algorithms #PlacementPrep #TechEducation
To view or add a comment, sign in
-
More from this author
Explore content categories
- Career
- Productivity
- Finance
- Soft Skills & Emotional Intelligence
- Project Management
- Education
- Technology
- Leadership
- Ecommerce
- User Experience
- Recruitment & HR
- Customer Experience
- Real Estate
- Marketing
- Sales
- Retail & Merchandising
- Science
- Supply Chain Management
- Future Of Work
- Consulting
- Writing
- Economics
- Artificial Intelligence
- Employee Experience
- Workplace Trends
- Fundraising
- Networking
- Corporate Social Responsibility
- Negotiation
- Communication
- Engineering
- Hospitality & Tourism
- Business Strategy
- Change Management
- Organizational Culture
- Design
- Innovation
- Event Planning
- Training & Development
👍