Python 进阶 - 第十五节


📋 本节要点

知识点 说明
访问限制 隐藏内部细节,保护数据安全
私有属性 以 __ 开头,外部不能直接访问
私有方法 以 __ 开头,通过公开方法间接调用
公开方法 通过公开方法获取/设置私有属性
@property 将方法转为属性访问
命名规范 四种下划线形式含义不同

1. 私有属性与私有方法

在属性或方法前加双下划线 __,外部不能直接访问,这就是访问限制。

class Person:
    def __init__(self, name, age):
        self.name = name       # 公开属性
        self.__age = age       # 私有属性

    def __secret(self):        # 私有方法
        print("这是私有方法")

p = Person("张三", 20)

print(p.name)      # 张三 - 可以访问
# print(p.__age)   # 报错!不能直接访问私有属性
# p.__secret()     # 报错!不能直接调用私有方法

2. 公开方法间接访问

可以通过公开的方法间接访问私有属性和方法,在方法中可以添加验证逻辑。

2.1 通过方法访问私有属性

class Person:
    def __init__(self, name, age):
        self.name = name
        self.__age = age

    # 获取私有属性
    def get_age(self):
        return self.__age

    # 设置私有属性,可添加验证
    def set_age(self, age):
        if age > 0 and age < 150:    # 参数验证
            self.__age = age
        else:
            print("年龄不合法!")

p = Person("张三", 20)
print(p.get_age())   # 20
p.set_age(25)
print(p.get_age())   # 25
p.set_age(200)       # 年龄不合法!

2.2 公开方法调用私有方法

class Person:
    def __init__(self, name, age):
        self.name = name
        self.__age = age

    def __secret(self):
        print("这是秘密")

    # 公开接口调用私有方法
    def call_secret(self):
        self.__secret()

p = Person("张三", 20)
p.call_secret()  # 这是秘密

3. @property 属性访问器

用 @property 可以像访问属性一样调用方法,代码更简洁优雅:

class Person:
    def __init__(self, name, age):
        self.name = name
        self.__age = age

    @property               # getter:p.age 即可获取
    def age(self):
        return self.__age

    @age.setter              # setter:p.age = 25 即可设置
    def age(self, value):
        if 0 < value < 150:
            self.__age = value
        else:
            print("年龄不合法!")

p = Person("张三", 20)
print(p.age)   # 20(像访问属性一样)
p.age = 25     # 像设置属性一样(自动调用 setter)
print(p.age)   # 25

4. 实战:银行账户

class BankAccount:
    def __init__(self, owner, balance=0):
        self.owner = owner
        self.__balance = balance  # 私有属性,禁止外部直接修改

    @property
    def balance(self):
        return self.__balance

    def deposit(self, amount):
        if amount > 0:
            self.__balance += amount
            print(f"存款 {amount} 元,余额:{self.__balance}")

    def withdraw(self, amount):
        if 0 < amount <= self.__balance:
            self.__balance -= amount
            print(f"取款 {amount} 元,余额:{self.__balance}")
        else:
            print("余额不足!")

acc = BankAccount("张三", 1000)
acc.deposit(500)    # 存款 500 元,余额:1500
acc.withdraw(200)   # 取款 200 元,余额:1300
# acc.__balance = 99999  # 报错!不能直接修改私有属性
print(acc.balance)  # 1300(通过 @property 安全访问)

5. 下划线命名规范

写法 含义 示例
name 公开属性,可自由访问 self.name
_name 受保护属性,约定不直接访问 self._internal
__name 私有属性,名称重整机制 self.__age
__name__ 魔法方法/属性 __init__, __str__

访问限制的好处:保护数据不被意外修改,添加验证逻辑,降低代码耦合度,方便后续重构。


下一节预告:递归函数