
Python Attributes: Understanding How They Work 🐍
Attributes are the foundation of Python's object model, but most beginners (and even many mid-level developers) use them intuitively without understanding what happens under the hood. The result is unpredictable code behavior, memory bloat, and spaghetti APIs.
Let's dive into the nuances 👇
1️⃣ Method Resolution Order (MRO)
Python follows the principle: object first, then class.
When you access
obj.attr, the interpreter first looks in obj.__dict__. If not found, it goes to Class.__dict__.If you accidentally assign something to
obj.attr, you create an instance attribute that shadows the class attribute.class Hero:
weapon = "Sword"
h = Hero()
h.weapon = "Gun" # Now h has its own weapon, while the class still has a swordThis is not a bug, it's a feature, but control it. If you want to change an attribute for all instances, modify the class.
2️⃣
__dict__ vs __slots__By default, every object has
__dict__ — a hash table (dictionary) storing attributes. This is flexible but memory-heavy.If you create millions of objects of the same type, use
__slots__.🔵What it does: It prevents the creation of
__dict__ for instances, fixing the set of attributes in memory (like an array).🔵Benefit: 25-30% less memory consumption and slightly faster access.
🔵Cost: You lose the dynamic ability to add new attributes on the fly.
3️⃣ The Illusion of Encapsulation
Python has no "private" fields. At all.
Constructs like
__attribute are not data protection but name mangling. Python simply renames the variable to _ClassName__attribute to avoid accidental overriding in subclasses.If you use
__ hoping no one will access your data, anyone who knows dir() can see everything. Using _private (single underscore) means "don't touch, it's internal API." It's a matter of culture, not the compiler.Want to hide data? Use a single underscore
_ only as a signal to colleagues: "Don't touch this, it's internal."4️⃣ @property: Ethical Getter
Never write Java-style getters in Python (
get_value(), set_value()). If you need logic when accessing an attribute, use @property.@property allows you to turn a method into an attribute. You keep a clean API (dot access), but under the hood you can validate data, log access, or compute values on the fly.class DataStorage:
def __init__(self, value):
self._value = value
@property
def value(self):
return self._value
@value.setter
def value(self, new_val):
if not isinstance(new_val, int):
raise ValueError("Only int, baby")
self._value = new_valThis way you keep a clean interface:
obj.value = 10 looks as simple as working with a regular field, but you control what gets written.What other "magic" places in Python raise questions for you? Drop them in the comments, we'll discuss. 👇
#python_anatomy
Comments
0No comments yet.