Skip to content

封装性是面向对象的三大特性之一,它将数据(属性)和操作数据的方法捆绑在一起,形成一个独立的单元(类), 并对外部隐藏对象的内部实现细节,只提供对外的接口来访问和修改对象的状态。

1. 私有变量

1.1. 私有变量的定义

私有变量是一种封装机制,用于限制变量的访问范围,增强数据的安全性和类的封装性。
虽然没有严格意义上的私有变量,但可以通过命名约定和名称修饰来模拟私有变量。具体做法是在变量名前加双下划线 __。

python
class MyClass:
    def __init__(self):
        # 定义私有变量
        self.__private_variable = 10

在上述代码中,__private_variable 就是一个私有变量。

1.2. 私有变量的访问方式

私有变量可以在类的内部被访问和修改。

python
class MyClass:
    def __init__(self):
        self.__private_variable = 10

    def get_private_variable(self):
        return self.__private_variable

    def set_private_variable(self, value):
        self.__private_variable = value

# 创建类的实例
obj = MyClass()
# 在类内部访问私有变量
print(obj.get_private_variable())  

# 在类内部修改私有变量
obj.set_private_variable(20)
print(obj.get_private_variable())

1.3 类外部访问(不推荐)

Python 会对私有变量进行名称修饰,将其转换为 _类名__变量名 的形式。 虽然可以通过这种方式在类外部访问私有变量,但这违反了封装的原则,不建议这样做。

python
class MyClass:
    def __init__(self):
        self.__private_variable = 10

# 创建类的实例
obj = MyClass()
# 通过名称修饰后的名称访问私有变量
print(obj._MyClass__private_variable)

1.4. 私有变量的使用场景

私有变量可以防止外部代码直接访问和修改对象的内部数据,避免数据被意外修改或破坏。
例如,在一个银行账户类中,将账户余额设为私有变量,通过公共方法来进行存款和取款操作,确保余额的修改符合业务逻辑。

python
class BankAccount:
    def __init__(self, balance):
        # 私有变量,账户余额
        self.__balance = balance

    def deposit(self, amount):
        if amount > 0:
            self.__balance += amount
            print(f"存入 {amount} 元,当前余额:{self.__balance} 元。")
        else:
            print("存入金额必须大于 0。")

    def withdraw(self, amount):
        if amount > 0 and amount <= self.__balance:
            self.__balance -= amount
            print(f"取出 {amount} 元,当前余额:{self.__balance} 元。")
        else:
            print("取款失败,金额无效或余额不足。")

    def get_balance(self):
        return self.__balance

# 创建银行账户实例
account = BankAccount(1000)
# 存款操作
account.deposit(500)
# 取款操作
account.withdraw(300)
# 获取账户余额
print(account.get_balance())

输出内容:

text
存入 500 元,当前余额:1500 元。
取出 300 元,当前余额:1200 元。
1200

2. 私有变量与受保护变量的区别

除了私有变量,Python 还有受保护变量的概念,即在变量名前加单下划线 _。 受保护变量只是一种约定,表明该变量不建议在类外部直接访问,但实际上仍然可以访问,而私有变量通过名称修饰在一定程度上限制了外部访问。

python
class MyClass:
    def __init__(self):
        # 受保护变量
        self._protected_variable = 5
        # 私有变量
        self.__private_variable = 10

# 创建类的实例
obj = MyClass()
# 可以访问受保护变量
print(obj._protected_variable)  
# 可以通过名称修饰访问私有变量
print(obj._MyClass__private_variable)

3. 私有方法

私有方法和私有变量类似,是一种封装机制,用于限制方法的访问范围,增强类的封装性和安全性。

3.1. 私有方法的定义

过在方法名前加双下划线 __ 来定义私有方法。

python
class MyClass:
    def __init__(self):
        pass

    # 定义私有方法
    def __private_method(self):
        return "这是一个私有方法"

在上述代码中,__private_method 就是一个私有方法。

3.2. 私有方法的调用方式

私有方法可以在类的内部被其他方法调用。

python
class MyClass:
    def __init__(self):
        pass

    def __private_method(self):
        return "这是一个私有方法"

    def public_method(self):
        # 在类内部调用私有方法
        result = self.__private_method()
        return result

# 创建类的实例
obj = MyClass()
# 通过公共方法间接调用私有方法
print(obj.public_method())

3.3. 类外部调用(不推荐)

和私有变量一样,Python 会对私有方法进行名称修饰,将其转换为 _类名__方法名 的形式。 虽然可以通过这种方式在类外部调用私有方法,但这违反了封装的原则,不建议这样做。

python
class MyClass:
    def __init__(self):
        pass

    def __private_method(self):
        return "这是一个私有方法"

# 创建类的实例
obj = MyClass()
# 通过名称修饰后的名称调用私有方法
print(obj._MyClass__private_method())

3.4. 私有方法的应用场景

  • 私有方法可以隐藏类的内部实现细节,让外部代码只需要关注类提供的公共方法,而不需要了解其具体实现。
  • 私有方法通常是为类内部的其他方法服务的,不希望被外部代码直接调用。通过将这些方法设为私有,可以避免外部代码误调用,从而保证类的正常运行。

例如,在一个数据库连接类中,将一些初始化数据库连接的方法设为私有。

python
import sqlite3

class DatabaseConnection:
    def __init__(self, db_name):
        self.db_name = db_name
        self.__connect()

    def __connect(self):
        try:
            self.conn = sqlite3.connect(self.db_name)
            print("数据库连接成功")
        except sqlite3.Error as e:
            print(f"数据库连接失败: {e}")

    def execute_query(self, query):
        try:
            cursor = self.conn.cursor()
            cursor.execute(query)
            results = cursor.fetchall()
            return results
        except sqlite3.Error as e:
            print(f"执行查询出错: {e}")

    def close_connection(self):
        if self.conn:
            self.conn.close()
            print("数据库连接已关闭")

# 创建数据库连接实例
db = DatabaseConnection("example.db")
# 执行查询
results = db.execute_query("SELECT * FROM users")
print(results)
# 关闭连接
db.close_connection()

4. 私有方法与公共方法的区别

  • 公共方法:可以在类的外部直接调用,是类对外提供的接口,用于和外部代码进行交互。
  • 私有方法:只能在类的内部被调用,用于实现类的内部逻辑,隐藏类的实现细节,提高类的封装性和安全性。

综上所述,私有变量和私有方法是 Python 面向对象编程中实现封装的重要手段,合理使用私有方法可以提高代码的可维护性和安全性。