全部学科
Python全栈
python
NodeJS全栈
nodejs
小程序首页
📅 2026-05-19 7 分钟 ✍️ juanwangdev

Python 私有属性与方法

Python 通过命名约定实现属性的私有化,而非真正的访问控制。

三种命名约定

约定示例说明
单下划线_var内部使用,约定私有
双下划线__var名称重整(name mangling)
双下划线前后包围__var__魔术方法,系统定义

单下划线:约定私有

Python
class Person:
    def __init__(self, name):
        self._name = name  # 约定私有,但仍可访问

    def _get_internal(self):  # 约定私有方法
        return "内部方法"


p = Person("Alice")
print(p._name)        # Alice(可访问)
print(p._get_internal())  # 内部方法(可调用)

# 只是约定,不阻止外部访问

单下划线表示"内部使用",模块中 from module import * 不导入单下划线开头的对象。

双下划线:名称重整

Python
class Secret:
    def __init__(self):
        self.__private = "私有数据"  # 双下划线触发名称重整

    def __private_method(self):
        return "私有方法"


s = Secret()

# 直接访问失败
# print(s.__private)        # AttributeError
# print(s.__private_method())  # AttributeError

# 通过重整名称访问
print(s._Secret__private)       # 私有数据
print(s._Secret__private_method())  # 私有方法

# 查看 __dict__
print(s.__dict__)  # {'_Secret__private': '私有数据'}

名称重整规则

Python
__attr 变为 _ClassName__attr

避免子类覆盖

Python
class Base:
    def __init__(self):
        self.__value = 1


class Derived(Base):
    def __init__(self):
        super().__init__()
        self.__value = 2  # 不覆盖父类的 __value


d = Derived()
print(d._Base__value)      # 1(父类保留)
print(d._Derived__value)   # 2(子类独立)

私有属性的真正目的

Python
class BankAccount:
    def __init__(self, balance):
        self.__balance = balance

    def deposit(self, amount):
        if amount > 0:
            self.__balance += amount

    def withdraw(self, amount):
        if amount > 0 and amount <= self.__balance:
            self.__balance -= amount
        else:
            raise ValueError("余额不足")

    def get_balance(self):
        return self.__balance


acc = BankAccount(1000)
acc.deposit(500)
print(acc.get_balance())  # 1500

# 直接修改"私有"属性绕过验证
acc._BankAccount__balance = -1000  # 可以修改
print(acc.get_balance())  # -1000

Python 私有属性不是真正的访问控制,而是防止子类意外覆盖的机制。

getter 和 setter

使用方法

Python
class Temperature:
    def __init__(self, celsius):
        self._celsius = celsius

    def get_celsius(self):
        return self._celsius

    def set_celsius(self, value):
        if value < -273.15:
            raise ValueError("温度不能低于绝对零度")
        self._celsius = value

    def get_fahrenheit(self):
        return self._celsius * 9 / 5 + 32


t = Temperature(25)
print(t.get_celsius())      # 25
t.set_celsius(30)
print(t.get_celsius())      # 30

使用 @property

Python
class Temperature:
    def __init__(self, celsius):
        self._celsius = celsius

    @property
    def celsius(self):
        return self._celsius

    @celsius.setter
    def celsius(self, value):
        if value < -273.15:
            raise ValueError("温度不能低于绝对零度")
        self._celsius = value

    @property
    def fahrenheit(self):
        return self._celsius * 9 / 5 + 32


t = Temperature(25)
print(t.celsius)        # 25(像属性一样访问)
t.celsius = 30          # 像属性一样赋值,触发 setter
print(t.fahrenheit)     # 86.0

私有属性与继承

Python
class Parent:
    def __init__(self):
        self.__private = "父类私有"
        self._protected = "父类保护"


class Child(Parent):
    def __init__(self):
        super().__init__()
        self.__private = "子类私有"  # 新的私有属性,不覆盖

    def show(self):
        print(self._protected)      # 可访问
        # print(self.__private)      # AttributeError
        print(self._Child__private) # 子类私有
        print(self._Parent__private) # 父类私有


c = Child()
c.show()
# 父类保护
# 子类私有
# 父类私有

魔术方法

Python
class MyClass:
    def __init__(self):
        self.__private = "私有"

    def __str__(self):  # 魔术方法
        return "MyClass"


obj = MyClass()
print(obj)              # MyClass(调用 __str__)
print(obj.__dict__)     # {'_MyClass__private': '私有'}

# 魔术方法不会被名称重整
print(obj.__str__)      # <method-wrapper '__str' of MyClass object>

__xxx__ 是魔术方法命名空间,不会触发名称重整,用于 Python 特殊方法。

检查私有属性

Python
class PrivateChecker:
    def __init__(self):
        self._internal = "内部"
        self.__private = "私有"

    def list_attrs(self):
        print("实例属性:", self.__dict__)


p = PrivateChecker()
p.list_attrs()
# 实例属性: {'_internal': '内部', '_PrivateChecker__private': '私有'}

最佳实践

text
class GoodPractice:
    def __init__(self):
        # 公开属性:直接使用
        self.public = "公开"

        # 保护属性:单下划线,子类可访问
        self._protected = "保护"

        # 私有属性:双下划线,防止子类覆盖
        self.__private = "私有"

    def public_method(self):
        "公开方法"
        return self.__private  # 内部访问私有属性

    def _protected_method(self):
        "保护方法"
        return "保护方法"

    def __private_method(self):
        "私有方法"
        return "私有方法"

三种命名约定对比

约定真正私有用途
_var内部使用,约定私有
__var名称重整,防止子类覆盖
__var__魔术方法,系统定义

要点总结

要点说明
_xxx约定私有,仍可访问
__xxx名称重整为 _Class__xxx
__xxx__魔术方法,不重整
无真正私有Python 不强制访问控制
@property推荐的属性访问方式

Python 私有属性只是命名约定,本质都可访问;双下划线主要用于防止子类意外覆盖。

D:\git2\jwdev\articles\PYTHON\进阶\面向对象编程\私有属性与方法.md

📝 发现内容有误?点击此处直接编辑

← 上一篇 Python 描述符协议
下一篇 → Python 类与对象基础
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库