Python基础 – 封装与属性

封装与属性

项目:构建一个“银行账户系统”,展示封装、私有属性以及使用Python的@property装饰器。


01. 学习目标

在本课结束时,您将能够:

  • 理解封装及其在面向对象编程中的重要性
  • 使用私有属性___)来隐藏内部数据
  • 通过获取器/设置器方法访问私有变量
  • 使用@property装饰器简化代码
  • 为安全、不可变的数据创建只读属性

02. 问题场景

您正在构建一个银行账户系统,其中每个用户的余额必须是私有和受保护的。

用户不应直接修改余额 — 只能通过验证输入的受控方法进行修改。

封装确保敏感数据免受滥用。


03. 第一步 – 封装基础

封装隐藏了对象的内部细节,仅暴露必要的接口。

在Python中,以 ___ 开头的属性被视为 根据约定的私有属性

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

    def get_age(self):
        return self.__age       # 通过方法访问
p = Person("Sabin", 30)
print(p.name)        # Sabin
# print(p.__age)     # ❌ AttributeError
print(p.get_age())   # 30

04. 第2步 – 获取器和设置器方法

使用获取器和设置器方法安全地访问和修改私有属性。

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

    def get_balance(self):
        return self.__balance

    def set_balance(self, amount):
        if amount >= 0:
self.__balance = amount
        else:
            print("无效的余额")

acc = Account(100)
print(acc.get_balance())   # 100
acc.set_balance(200)
print(acc.get_balance())   # 200

05. 第3步 – 使用 @property

Python 的 @property 装饰器允许你创建 getter/setter 功能
同时将属性访问视为公共属性。

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

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

    @balance.setter
    def balance(self, amount):  # 设置器
        if amount >= 0:
            self.__balance = amount
        else:
            print("无效的余额")

acc = Account(100)
print(acc.balance)   # 100
acc.balance = 300
print(acc.balance)   # 300

现在您可以自然地访问和修改 balance,而不会破坏封装性。


06. 第四步 – 只读属性

仅定义一个 getter(没有 setter)以使属性变为只读

class Circle:
def __init__(self, r):
    self.__r = r

@property
def area(self):
    return 3.14 * self.__r * self.__r

c = Circle(5)
print(c.area)   # 78.5
# c.area = 100  # ❌ AttributeError: can't set attribute

07. 第5步 – 实践示例

示例 1:温度验证

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:   # 绝对零度检查
            self.__celsius = value
        else:
            print("无效的温度")

t = Temperature(25)
print(t.celsius)   # 25
t.celsius = -300   # 无效的温度

示例 2:具有只读成绩的学生

class Student:
    def __init__(self, name, grade):
        self.name = name
        self.__grade = grade

    @property
def grade(self):   # 只读属性
        return self.__grade

s = Student("Anna", "A")
print(s.name, s.grade)   # Anna A
# s.grade = "B"  # ❌ AttributeError: 无法设置属性

08. 小项目 – 安全银行账户

使用封装和属性构建一个简单的银行账户系统。

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

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

    @balance.setter
    def balance(self, amount):
        if amount >= 0:
            self.__balance = amount
        else:
            print("无效金额 — 余额不能为负数。")

    def deposit(self, amount):
        if amount > 0:
            self.__balance += amount
print(f"存款 {amount}. 新余额: {self.__balance}")
else:
    print("存款必须为正数。")

def withdraw(self, amount):
    if 0 < amount <= self.__balance:
        self.__balance -= amount
print(f"已提取 {amount}. 新余额: {self.__balance}")
        else:
            print("无效的提取金额。")

acc = BankAccount("Sabin", 1000)
acc.deposit(500)
acc.withdraw(200)
print("最终余额:", acc.balance)

输出:

存入500。新余额:1500
取出200。新余额:1300
最终余额:1300

09. 反射

你已经学习了如何:

  • 使用封装来保护数据完整性
  • 应用getter/setter 方法进行受控访问
  • 通过@property 装饰器简化代码
  • 为不可变数据创建只读属性
  • 在现实世界系统中应用这些概念(如银行系统)

更多