Name mangling với __private
Hiện tượng lạ
Phần tiêu đề “Hiện tượng lạ”class MyClass: def __init__(self): self.__private = "secret" self._protected = "internal" self.public = "open"
obj = MyClass()
print(obj.public) # "open" ✅print(obj._protected) # "internal" ✅print(obj.__private) # AttributeError! ❌
# Nhưng...print(obj._MyClass__private) # "secret" ✅ What?!What the Python?! __private không thật sự private?! 🤔
Giải thích
Phần tiêu đề “Giải thích”Name Mangling
Phần tiêu đề “Name Mangling”Python tự động đổi tên __name thành _ClassName__name:
class MyClass: def __init__(self): self.__x = 10
# Python tự động rename# self.__x → self._MyClass__xXem attributes
Phần tiêu đề “Xem attributes”class MyClass: def __init__(self): self.__private = "secret"
obj = MyClass()print(dir(obj))# [..., '_MyClass__private', ...]
# Access trực tiếpprint(obj._MyClass__private) # "secret"Conventions
Phần tiêu đề “Conventions”public - Public
Phần tiêu đề “public - Public”class MyClass: def __init__(self): self.public = "everyone can use"_protected - Protected (convention)
Phần tiêu đề “_protected - Protected (convention)”class MyClass: def __init__(self): self._protected = "internal use" # Convention: Đừng dùng bên ngoài class__private - Name mangled
Phần tiêu đề “__private - Name mangled”class MyClass: def __init__(self): self.__private = "avoid name collision" # Để tránh collision với subclassKhi nào dùng name mangling?
Phần tiêu đề “Khi nào dùng name mangling?”✅ Tránh collision trong inheritance
Phần tiêu đề “✅ Tránh collision trong inheritance”class Base: def __init__(self): self.__id = 1 # Name mangled
def get_id(self): return self.__id
class Derived(Base): def __init__(self): super().__init__() self.__id = 2 # KHÔNG conflict với Base.__id
d = Derived()print(d.get_id()) # 1 (Base.__id)print(d._Derived__id) # 2 (Derived.__id)Best Practices
Phần tiêu đề “Best Practices”✅ Dùng _single cho internal
Phần tiêu đề “✅ Dùng _single cho internal”class MyClass: def __init__(self): self._internal = "use with care" # ✅❌ Không dùng __double trừ khi cần
Phần tiêu đề “❌ Không dùng __double trừ khi cần”class MyClass: def __init__(self): self.__private = "rarely needed" # ❌ OverkillTóm tắt
Phần tiêu đề “Tóm tắt”Python naming conventions:
public- Public API_protected- Internal (convention only)__private- Name mangled (tránh collision)- ✅ Dùng
_singlecho internal- ⚠️
__doubleKHÔNG truly private!
Remember: Python không có true private, chỉ có conventions!