对象副本修改引发原对象突变?含DataFrame属性类的不可变实现求助
Got it, let's break this down clearly—you're hitting a classic reference vs. true copy problem here, and pandas DataFrames add a little extra complexity with their shallow vs. deep copy behavior. Let's walk through why your current approach isn't working, then fix it.
Why copy = self Fails
First off, copy = self doesn't create a new object—it just creates a new variable that points to the exact same instance as self. Any changes you make to copy will directly modify the original object because they're the same thing under the hood. That's why your original object is getting altered.
Why Even df.copy() Might Not Be Enough
Pandas' df.copy() method defaults to a shallow copy (deep=False). If your DataFrame contains mutable objects like lists, dictionaries, or other nested DataFrames, a shallow copy will still share those internal objects with the original. So modifying those nested elements in the copied DataFrame would still change the original.
The Fix: Create a New Instance with Deep Copied Data
To keep your original object immutable, you need to:
- Create a brand new instance of your class, not just a reference to the original.
- Deep copy the DataFrame attribute (and any other mutable attributes) to ensure the new instance has completely independent data.
Here's a concrete example:
import pandas as pd import copy class DataHolder: def __init__(self, df): # Store the DataFrame (we'll handle copying in operations) self.df = df # Example: Implement the addition operator def __add__(self, other): # 1. Deep copy the original DataFrame to avoid modifying it new_df = self.df.copy(deep=True) # 2. Perform the arithmetic operation on the copied DataFrame new_df += other.df # 3. Return a NEW instance of DataHolder with the modified DataFrame return DataHolder(new_df) # Repeat this pattern for other operators (__sub__, __mul__, etc.)
Test It Out
# Create original objects original_df = pd.DataFrame({"value": [1, 2, 3]}) obj1 = DataHolder(original_df) obj2 = DataHolder(pd.DataFrame({"value": [10, 20, 30]})) # Perform addition—this returns a NEW object result_obj = obj1 + obj2 # Check original is unchanged print("Original DataFrame:") print(obj1.df) # Still shows [1,2,3] # Check result is correct print("\nResult DataFrame:") print(result_obj.df) # Shows [11,22,33]
Key Takeaways
- Never use
copy = self—it's just a reference, not a new object. - Always use
df.copy(deep=True)for pandas DataFrames when you need full independence (orcopy.deepcopy(self.df)for even more nested cases). - Arithmetic operator methods (like
__add__,__mul__) should return a new instance of your class, not modifyselfin place. This ensures immutability by design.
内容的提问来源于stack exchange,提问作者rgk

