The Subtle Danger of Mutable Class Variables in Python One of the most common — and surprisingly tricky — mistakes in Python OOP is using mutable class variables. Consider this example: class ShoppingCart: items = [] # ❌ Mutable class variable def add_item(self, item): self.items.append(item) cart1 = ShoppingCart() cart2 = ShoppingCart() cart1.add_item("Laptop") print(cart1.items) # ['Laptop'] print(cart2.items) # ['Laptop'] Why does cart2 contain "Laptop" even though we never added anything to it? Because items is defined at the class level, not the instance level. And since lists are mutable, every instance shares the same underlying object. This isn’t a bug in Python. It’s how attribute lookup works: • Python first checks the instance. • If not found, it checks the class. • Mutable class attributes are shared across all instances. ⸻ The Correct Approach Initialize mutable data inside __init__: class ShoppingCart: def __init__(self): self.items = [] # ✅ Instance-specific list def add_item(self, item): self.items.append(item) Now each object has its own independent list. ⸻ Rule of Thumb Use class variables for: • Constants • Shared configuration • Intentionally shared state Avoid them for: • Lists • Dictionaries • Sets • Any mutable structure meant to be instance-specific Small oversight. Big debugging session. Understanding how Python handles attribute resolution prevents subtle shared-state bugs that can be painful to trace in production systems. #Python #OOP #SoftwareEngineering #BackendDevelopment #CleanCode
Python OOP Gotcha: Mutable Class Variables
More Relevant Posts
-
Day 11 – Python Functions: Returns, Callbacks, Lambda & Recursion Today’s focus was on going deeper into Python functions and understanding how flexible and powerful they really are. What I learned and practiced today: How return works in functions Any code written after return is ignored A function can return values and also be printed when called Difference between: Calling a function Assigning a function to a variable and calling it later Functions are first-class objects in Python, which means: A function can be assigned to a variable Stored inside data structures like lists and tuples Passed as an argument to another function (callback function) Returned from another function (higher-order function) Higher-Order & Callback Functions: A function that takes another function as an argument is a higher-order function A function passed as an argument is called a callback function Practiced executing functions stored inside a list Anonymous (Lambda) Functions: Learned how to define functions without a name using lambda Practiced: Lambda without parameters Lambda with single and multiple parameters Default values in lambda *args and **kwargs with lambda functions Recursion Concepts: A function calling itself based on a condition is called recursion Understood: Base condition to stop recursion Memory usage concerns with recursion Why loops are often preferred over recursion Implemented: Printing numbers using recursion Printing ranges using recursion Problem-Solving with Functions: Multiplication table using a function Printing numbers in a given range Prepared tasks for: Practicing all function types with syntax and examples Re-implementing previous problems using functions Using both user-defined and predefined functions Day by day, my understanding of Python is getting stronger, especially around functional concepts and code reusability. #Python #PythonFunctions #LambdaFunctions #Recursion #HigherOrderFunctions #CallbackFunctions #ProgrammingBasics #LearningPython #DailyLearning #StudentDeveloper
To view or add a comment, sign in
-
🧠 Python Concept That Powers @property & Methods: __set_name__ Hidden hook during class creation 👀 🤔 What Is __set_name__? When a class is created, Python tells each descriptor: 👉 “Hey, your attribute name is x.” That hook is __set_name__. 🧪 Example class Field: def __set_name__(self, owner, name): self.name = name def __get__(self, instance, owner): return instance.__dict__.get(self.name) def __set__(self, instance, value): instance.__dict__[self.name] = value class User: age = Field() name = Field() u = User() u.age = 20 print(u.age) The descriptor automatically knows its field name 🎯 🧒 Simple Explanation Imagine giving kids name badges 🏷️ The teacher tells each kid: 👉 “Your name is Asha.” That’s __set_name__. 💡 Why This Is Powerful ✔ Self-aware descriptors ✔ ORM-like fields ✔ Framework internals ✔ Cleaner reusable components ⚡ Real-World Use 💻 Django models 💻 ORMs 💻 Validation frameworks 💻 Data descriptors 🐍 Python classes don’t just define attributes. 🐍 They introduce them by name 🐍 __set_name__ is one of those hooks you never see — but frameworks rely on it. #Python #PythonTips #PythonTricks #AdvancedPython #CleanCode #LearnPython #Programming #DeveloperLife #DailyCoding #100DaysOfCode
To view or add a comment, sign in
-
-
🚀 Day 17/30 – Python OOPs Challenge 💡 Method Overloading in Python In some languages (like Java), we can create multiple methods with the same name but different parameters. That is called Method Overloading. But what about Python? 🤔 🔹 Important: Python does NOT support traditional method overloading directly. If we write: ``` class Test: def show(self): print("First") def show(self): print("Second") ``` Only the second method will work. Output: Second The first one gets overwritten. 🔹 So how do we achieve overloading in Python? We use: - Default arguments - Variable-length arguments (*args) 🔹 Example using default arguments: ``` class Calculator: def add(self, a, b=0, c=0): print(a + b + c) c1 = Calculator() c1.add(5) c1.add(5, 10) c1.add(5, 10, 15) ``` 🔹 What happened here? Same method name → different number of arguments → works fine. This is how Python handles method overloading. 📌 Key takeaway: Python achieves method overloading using *default arguments or args. 👉 Day 18: Abstraction in Python (coming tomorrow) 👍 Like | 💬 Comment | 🔁 Share 📍 Follow me to learn Python OOP step by step #Python #OOP #LearningInPublic #30DaysOfPython #CodingJourney
To view or add a comment, sign in
-
🐍 Python Error Explained — Default Argument Order Matters ⚠️ Let’s look at this function 👇 def greet(first_name="Danial", last_name): print(f"how are you {first_name} {last_name}") greet(last_name="Haider") ❌ This code causes a SyntaxError 💡 Why the Error Happens In Python: 👉 Parameters with default values must come AFTER required parameters You wrote: default parameter → first_name="Danial" required parameter → last_name ❌ This order is not allowed ✅ Correct Version #1 — Required First, Default After def greet(last_name, first_name="Danial"): print(f"how are you {first_name} {last_name}") greet("Haider") 👉 Output: how are you Danial Haider ✅ Correct Version #2 — Give Defaults to Both def greet(first_name="Danial", last_name="Raza"): print(f"how are you {first_name} {last_name}") greet(last_name="Haider") 👉 Output: how are you Danial Haider 🔑 Rule to Remember Required parameters → FIRST Default parameters → LAST 🚀 Understanding parameter order prevents one of the most common beginner errors in Python 💻 #Python #Coding #Programming #LearnToCode #Developer
To view or add a comment, sign in
-
Python Default Arguments 🐍🐍 Default Arguments Powerful but Dangerous. Let’s see why. Basic Example def greet(name="Guest"): print(f"Hello {name}") greet() # Hello Guest greet("Rahul") # Hello Rahul #Looks simple. But here is the important detail: 👉 Default arguments are evaluated only once — when the function is defined, not when it is called. The Classic Python Trap def add_item(item, items=[]): items.append(item) return items print(add_item(1)) # [1] print(add_item(2)) # [1, 2] print(add_item(3)) # [1, 2, 3] Most people expect: [1] [2] [3] But Python keeps reusing the same list object. Why? Because the default list "[]" was created once at function definition time and reused in every call. The Correct Way def add_item(item, items=None): if items is None: items = [] items.append(item) return items Now every call gets a fresh list. Why Python Works This Way Python stores default arguments inside the function object: function.__defaults__ They are not recreated each time the function runs. This design improves performance but can introduce subtle bugs. #Takeaway ✔ Default arguments are evaluated once at definition time ✔ Mutable defaults ("list", "dict", "set") can cause shared state bugs ✔ Use "None" as a safe default when mutation is involved #Python #PythonTips #Programming #SoftwareEngineering #PythonDeveloper
To view or add a comment, sign in
-
-
🧠 Python Concept That Explains Class Namespaces: __prepare__ in Metaclasses Before a class is created… Python prepares its namespace 👀 🤔 What Is __prepare__? When Python executes: class MyClass: x = 1 y = 2 It first asks the metaclass: 👉 “What mapping should I use to store attributes?” That hook = __prepare__. 🧪 Example class OrderedMeta(type): @classmethod def __prepare__(mcls, name, bases): return {} def __new__(mcls, name, bases, namespace): print(list(namespace.keys())) return super().__new__(mcls, name, bases, namespace) class Demo(metaclass=OrderedMeta): a = 1 b = 2 c = 3 ✅ Output ['a', 'b', 'c'] Metaclass saw class body order 🎯 🧒 Simple Explanation 🧸 Before kids put toys in a box, teacher chooses the box. 🧸 That box = namespace. 🧸 Choice = __prepare__. 💡 Why This Matters ✔ Ordered class attributes ✔ DSLs & frameworks ✔ Enum internals ✔ ORM field order ✔ Metaprogramming ⚡ Real Uses 💻 Enum preserves order 💻 Dataclasses fields 💻 ORM column order 💻 Serialization frameworks 🐍 In Python, even class bodies have a setup phase 🐍 __prepare__ decides how attributes are collected, before the class even exists. #Python #PythonTips #PythonTricks #AdvancedPython #CleanCode #LearnPython #Programming #DeveloperLife #DailyCoding #100DaysOfCode
To view or add a comment, sign in
-
-
Accessing Dictionary Values Safely in Python Dictionaries are powerful data structures in Python that store data as key-value pairs, allowing for efficient access. Accessing items correctly is essential, especially when the existence of a key is uncertain. The most straightforward way to retrieve a value is by using the key directly, as shown with `person['name']`. This method works seamlessly, but if a key does not exist, Python raises a `KeyError`, potentially leading to runtime errors. That's where the `get` method becomes advantageous. It allows for safe retrieval; if the key isn’t found, it returns `None` instead of causing a crash. Another valuable feature of the `get` method is its ability to specify a default return value. In our example, when looking for 'country', if it doesn’t exist, we can have it return 'Unknown'. This ability is particularly useful in real-world applications, ensuring that our code remains robust and gracefully handles missing data. Understanding the difference between direct access and the `get` method becomes crucial when working with dynamic datasets or user-generated content, where missing keys are commonplace. The choice of method can significantly impact how well your code handles such situations. Quick challenge: In what scenario would you prefer to use the `get` method over direct key access when dealing with dictionaries? #WhatImReadingToday #Python #PythonProgramming #Dictionaries #PythonTips #Programming
To view or add a comment, sign in
-
-
🔵 Python Conditional Statements with Conditions In Python, conditional statements are used to make decisions based on conditions that evaluate to True or False. These conditions usually involve relational and logical operators, allowing programs to respond intelligently to different inputs. 📌 Main Conditional Statements in Python: 1️⃣ if Statement Executes a block of code only if the given condition is True. 👉 Example condition: age >= 18 2️⃣ if–else Statement Executes one block when the condition is True and another block when it is False. 👉 Example condition: marks >= 40 3️⃣ if–elif–else Statement Used when multiple conditions need to be checked. Conditions are evaluated from top to bottom. 👉 Example conditions: • marks >= 90 • marks >= 60 4️⃣ Nested if Statement An if statement inside another if, used when one condition depends on another. 👉 Example conditions: • num > 0 • num % 2 == 0 🔑 Conditions commonly use: ✔ Relational operators: > < >= <= == != ✔ Logical operators: and, or, not ✔ Membership operators: in, not in ✨ Mastering conditions helps in building smart, efficient, and decision-based Python programs. #Python #ConditionalStatements #PythonBasics #Coding #Programming #LearningJourney #InternshipDiary #TechLearning
To view or add a comment, sign in
-
🐍 Python Lists — The Swiss Army Knife of Data Structures If you're learning Python, mastering lists is non-negotiable. Here's everything you need in one place: ✅ Create python fruits = ["apple", "banana", "cherry"] ✅ Access python fruits[0] # "apple" fruits[-1] # "cherry" (last item!) ✅ Add & Remove python fruits.append("mango") # add to end fruits.insert(1, "grape") # add at index fruits.remove("banana") # remove by value fruits.pop() # remove last item ✅ Slice python fruits[1:3] # items from index 1 to 2 fruits[::-1] # reverse the list ✅ Loop python for fruit in fruits: print(fruit) ✅ List Comprehension (the magic trick 🪄) python squares = [x**2 for x in range(10)] Lists are ordered, mutable, and allow duplicates — making them perfect for storing and manipulating collections of data. Once you're comfortable with lists, you're ready to tackle tuples, sets, and dictionaries too. 💬 What Python concept do you wish you learned earlier? Drop it below 👇 #Python #Programming #CodingTips #DataScience #LearnToCode #100DaysOfCode
To view or add a comment, sign in
-
🚀 Revisiting Python Fundamentals Day 6: Flow Control Statements in Python In Python, code normally executes line by line from top to bottom. But real-world programs need more than that. They need to: Make decisions Repeat actions Control execution flow That’s where Flow Control Statements come in. Flow control statements decide which block of code runs and how many times it runs. They are mainly divided into three categories: 🔹 1️⃣ Decision Statements These are used when a program needs to choose between alternatives. Python provides: if elif else Example: age = 18 if age >= 18: print("Eligible to vote") else: print("Not eligible") Here: Python checks the condition age >= 18 If it is True, the first block runs If False, the else block runs Decision statements allow programs to behave differently based on conditions. 🔹 2️⃣ Looping Statements Loops are used when a block of code needs to run multiple times. Python provides: for while For Loop Used when the number of iterations is known. for i in range(3): print(i) This prints values from 0 to 2. While Loop Used when execution depends on a condition. count = 0 while count < 3: print(count) count += 1 The loop runs until the condition becomes False. Loops reduce repetition and make programs efficient. 🔹 3️⃣ Control Statements These are used inside loops to change their normal behavior. break → immediately exits the loop continue → skips the current iteration pass → placeholder that does nothing Example using break: for i in range(5): if i == 3: break print(i) The loop stops when i becomes 3. #Python #FlowControl #PythonBasics #LearnPython #Programming
To view or add a comment, sign in
-
Explore related topics
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