Skip to main content

06-私有变量和方法

在 Python 中,类的属性和方法默认是公有的(public),但可以通过 私有(private) 机制 限制外部访问

虽然 Python 没有真正的私有变量,但可以使用 双下划线__ 前缀来 模拟私有,让变量或方法 不能直接被外部访问

1.私有变量(Private Variables)

  • 定义私有变量

在 Python 类中:

  • self.变量名公有(public)的,外部可以访问。
  • self._变量名 仅是 约定俗成的保护变量(protected),仍然可以访问,但不建议外部直接访问。
  • self.__变量名私有变量(private)不能 直接被外部访问。

🔸 示例

class Person:
def __init__(self, name, age):
self.name = name # 公有变量
self._nickname = "无名" # 受保护变量(建议内部使用)
self.__age = age # 私有变量

def show_info(self):
return f"姓名: {self.name}, 年龄: {self.__age}"

p = Person("Alice", 25)

print(p.name) # ✅ 可以访问公有变量
print(p.show_info()) # ✅ 访问私有变量的方法

print(p.__age) # ❌ AttributeError: 'Person' object has no attribute '__age'

输出:

Alice
姓名:Alice,年龄:25
Traceback (most recent call last):
File "C:\Users\EDY\code\python-tutorial\包\__init__.py", line 16, in <module>
print(p.__age)
^^^^^^^
AttributeError: 'Person' object has no attribute '__age'

2.私有方法(Private Methods)

🔹 定义私有方法

  • def 方法名(self): 定义公有方法,可以被外部调用。
  • def _方法名(self): 定义 受保护方法,约定 只能在类或子类中使用
  • def __方法名(self): 定义 私有方法不能被外部直接调用

🔸 示例

class Car:
def __init__(self, brand):
self.brand = brand

def start(self):
self.__engine_check() # 在内部调用私有方法
print(f"{self.brand} 启动")

def __engine_check(self): # 私有方法
print("发动机检测完成")


car = Car("Tesla")
car.start() # ✅ 通过公有方法 start() 间接调用私有方法

car.__engine_check() # ❌ AttributeError: 'Car' object has no attribute '__engine_check'

🔹 说明:

  • start()公有方法,可以外部调用。
  • __engine_check()私有方法,不能外部调用,但可以在类的内部调用。

3.私有变量和方法的访问方式

虽然 Python 不允许直接访问私有属性和方法,但仍然可以通过以下两种方式访问:

(1)提供公有方法(推荐做法)

(2)使用 Python 的名称重整(Name Mangling)机制

🔹 方式 1:通过公有方法访问私有变量

class BankAccount:
def __init__(self, balance):
self.__balance = balance # 私有变量

def get_balance(self): # 通过公有方法访问
return self.__balance

account = BankAccount(1000)
print(account.get_balance()) # ✅ 1000

✅ 推荐方式:

  • 提供公有方法 get_balance() 来访问 __balance,保证数据封装性。

🔹 方式 2:使用 Name Mangling 访问私有变量

Python 不会真正隐藏私有变量,而是修改变量名称,即:

__变量名_类名__变量名

class Person:
def __init__(self, name, age):
self.__age = age # 私有变量

p = Person("Alice", 25)
print(p._Person__age) # ✅ 访问私有变量(不推荐)

❌ 不推荐:

  • 访问 p._Person__age 破坏了封装性,容易出错,不建议这样做。

4.私有变量和继承

私有变量 __变量名 不能被子类直接访问,但 受保护变量 _变量名 可以被子类访问。

class Parent:
def __init__(self):
self._protected = "受保护变量"
self.__private = "私有变量"

class Child(Parent):
def show(self):
print(self._protected) # ✅ 可以访问受保护变量
print(self.__private) # ❌ AttributeError

c = Child()
c.show()

🔹 说明:

  • _protected 可以在子类中访问。
  • __private 不能在子类中访问。

5.使用 property 保护私有变量(封装)

Python 提供 @property 装饰器,可以用于 保护私有变量,但 允许外部读取和修改,类似于 Java 的 gettersetter 方法。

class Student:
def __init__(self, name, score):
self.name = name
self.__score = score # 私有变量

@property
def score(self): # 读取私有变量
return self.__score

@score.setter
def score(self, value): # 修改私有变量
if 0 <= value <= 100:
self.__score = value
else:
raise ValueError("分数必须在 0-100 之间")

s = Student("小明", 85)
print(s.score) # ✅ 85
s.score = 95 # ✅ 修改分数
print(s.score) # ✅ 95
s.score = 200 # ❌ 抛出异常

🔹 说明:

  • @property 使 score 方法变成属性,允许 s.score 直接访问 __score
  • @score.setter 限制修改范围,确保 score 只能在 0~100 之间。

6.什么时候使用私有变量和方法?

应该使用私有变量和方法的情况

  1. 不希望外部直接修改某些变量,例如 银行账户余额
  2. 防止子类误修改父类的重要变量,确保数据安全。
  3. 隐藏实现细节,只提供必要的接口,提高代码可读性。

不推荐滥用私有变量

  • Python 没有真正的私有变量,使用 __ 只是 弱封装,并不影响访问。
  • 过度封装会降低代码可维护性,通常 _protected 变量已经足够。

总结

类型命名方式访问权限建议使用场景
公有变量self.name任何地方都可以访问适用于普通属性
受保护变量self._name仅限内部或子类访问(但仍可外部访问)约定为内部使用
私有变量self.__name不能直接访问,但可通过 _类名__变量 访问确保关键数据不被修改
公有方法def method(self):任何地方都可以访问供外部调用
私有方法def __method(self):仅限类内部调用内部逻辑封装

Python 的私有机制是 约定俗成,并非真正强制。合理使用 __ 可以增强封装性,提供代码安全性和可维护性! 🚀