封装、 私有方法、装饰器-知识点

本文深入探讨Python中的封装概念,包括私有属性和方法的使用,以及如何通过gettersetter方法安全地修改私有属性。同时,文章详细介绍了装饰器的原理和应用,包括其在不修改原函数情况下扩展功能的方法,以及如何创建带返回值和参数的装饰器。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、封装引入
封装的体现: 将属性或者方法 私有化 就是在变量或者方法名称前面添加__
注意: 私有属性或者方法可以在自己的类内部使用。
正常修改 : 一般提供一对 getter setter方法

class Person:
    def __init__(self, name, age):
        self.name = name
        self.__age = age  # self.__age就是一个私有属性,对象就不能使用了

    # 给私有属性设置值
    def set_age(self, age):
        if age < 0 or age > 150:
            print('不合法啊,sb')
            return
        self.__age = age

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

    def __str__(self):
        msg = '姓名:{},年龄{}'.format(self.name, self.__age)
        return msg

正常情况

person = Person('zs', 20)
person.age = -20
print(person)

age属性变成私有

person = Person('zs', 20)
person.__age = -20  # 不能修改
print(person)

正常修改

person = Person('zs', 20)
person.set_age(21)
print(person)

二、私有方法
在方法前添加__例如__send_message()
私有方法的作用:在开发的过程中保护核心代码。在类的外部不能使用(对象不能调用私有方法)

class A:
    def test(self):
        print('test')
    def __test1(self):
        print('test1')
    def test2(self):
        print('test2')
        self.__test1()#可以在类的内部调用
a=A()
a.test()
# a.__test1()在外部使用报错
# a.test2()

应用场景:

class Phone:
    def __phone(self):
        print('正在打电话。。。')

    def phone(self,money):
        if money>0:
            self.__phone()
        else:
            print('10086提醒欠费了。。。')
tel=Phone()
tel.phone(20)
tel.phone(-1)

三、封装后的限制

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

    def set_age(self, age):
        if age < 0 or age > 150:
            print('不合法,输入有误')
            return
        self.__age = age

    def get_age(self):
        return self.__age

    def __str__(self):
        msg = '姓名:{},年龄{}'.format(self.name, self.__age)
        return msg
        
person = Person('zs', 20)
print(person.__dict__)# {'name': 'zs', '_Person__age': 20}
person.__age = 10  # 因为这种方式 保存到字典的时候不会自动变成 _类名___变量名
# 因此不能覆盖类中私有属性的值,但是会添加到对象的内存中。
print(person.__dict__)#{'name': 'zs', '_Person__age': 20, '__age': 10}

四、装饰器
1、装饰器函数的本质:一个闭包函数
2、装饰器函数的作用:在不修改原函数及其调用方式的情况下,对原函数功能进行扩展。
3、语法糖—>格式:@装饰器名称
4、创建带返回值的装饰器
5、创建传递参数的装饰器
我们来测试下方函数执行完毕用的时间

 def func()
    for i in range(100000000):
           pass
 func()

首先调用time模块

import time

1)正常函数求法:

def func():
    start = time.time()
    for i in range(100000000):
        pass
    end = time.time()
    print(end - start)
func()

2)闭包函数求法:

def func():
    for i in range(100000000):
        pass
def outter(fun):
    def inner():
        start = time.time()
        fun()
        end = time.time()
        print(end - start)
    return inner
inner = outter(func)
inner()

3)使用语法糖

def outter(fun):
    print('xxxx')
    def inner():
        start = time.time()
        fun()
        end = time.time()
        print(end - start)
    return inner
    
@outter  # inner = outter(func)
def func():
    for i in range(100000000):
        pass
func()

4)带返回值的装饰器

def timer(fun):
    def inner():
        start = time.time()
        ret = fun()
        end = time.time()
        print(end - start)
        return ret
    return inner
@timer  # func = timer(func)
def func():
    for i in range(100000000):
        pass
    return 'ok'
ret = func()
print(ret)
func = timer(func)
func()

5)创建传递参数的装饰器

def timer(fun):
    def inner(s):
        start = time.time()
        ret = fun(s)  # func()
        end = time.time()
        print(end - start)
        return ret
    return inner
    
@timer
def func(s):
    for i in range(100000000):
        pass
    return s
ret = func('hello')  # func ---> inner()
print(ret)

6)返回任意参数

def timer(fun):
    def inner(*args, **kwargs):
        start = time.time()
        ret = fun(*args, **kwargs)  # func()
        end = time.time()
        print(end - start)
        return ret
    return inner

@timer
def func(*args, **kwargs):
    for i in range(100000000):
        pass
    return args, kwargs
ret = func('hello', name='zs')  # func ---> inner()
print(ret)
<think>我们正在寻找关于Python面向对象高阶编程的练习题目,重点包括:继承、多态、封装、访问控制、装饰器。 根据用户提供的引用,我们了解到: 引用[1]:面向对象三要素——封装、继承与多态。 引用[2]和[3]:装饰器的概念、实现原理(函数嵌套、闭包)以及应用场景(日志、性能测试、事务处理等)。 因此,我们将设计一些练习题目,涵盖这些主题,并按照从基础到高级的顺序排列。 注意:由于是练习题目,每个题目应包含问题描述和参考代码(或要求用户实现的部分),以及必要的解释。 设计思路: 1. 封装与访问控制:设计一个,展示私有属性、保护属性和公有属性,以及使用@property装饰器。 2. 继承与多态:设计一个继承体系,要求子重写父方法,展示多态行为。 3. 装饰器:设计一个自定义装饰器,用于增强方法或函数,例如日志记录、性能测试等。 4. 综合应用:设计一个稍复杂的系统,整合封装、继承、多态和装饰器。 下面给出具体的练习题目:</think>### Python面向对象高阶编程练习题目 以下练习涵盖**继承、多态、封装、访问控制、装饰器**等核心概念,每个题目均包含需求描述和参考实现框架。 --- #### **练习1:银行账户系统(封装与访问控制)** **需求**: 1. 实现`Account`基,包含私有属性`_balance`(余额)和`account_id`(账户ID) 2. 使用`@property`和`@setter`装饰器控制余额访问 3. 子`SavingsAccount`(储蓄账户)需保留最低余额100元 4. 子`CheckingAccount`(支票账户)允许透支 ```python class Account: def __init__(self, account_id, balance=0): self.account_id = account_id self._balance = balance # 私有属性 @property def balance(self): return self._balance def deposit(self, amount): if amount > 0: self._balance += amount return True return False def withdraw(self, amount): raise NotImplementedError("子需实现此方法") class SavingsAccount(Account): def withdraw(self, amount): if 0 < amount <= self._balance - 100: self._balance -= amount return True return False class CheckingAccount(Account): def withdraw(self, amount): if amount > 0: self._balance -= amount return True return False # 测试代码 savings = SavingsAccount("SA001", 500) savings.withdraw(450) # 失败(需保留100元) print(savings.balance) # 输出: 500 ``` --- #### **练习2:形状计算系统(继承与多态)** **需求**: 1. 基`Shape`定义抽象方法`area()`和`perimeter()` 2. 子`Circle`、`Rectangle`实现具体计算逻辑 3. 通过多态统一调用不同子方法 ```python from abc import ABC, abstractmethod import math class Shape(ABC): @abstractmethod def area(self): pass @abstractmethod def perimeter(self): pass class Circle(Shape): def __init__(self, radius): self.radius = radius def area(self): return math.pi * self.radius ** 2 def perimeter(self): return 2 * math.pi * self.radius class Rectangle(Shape): def __init__(self, width, height): self.width = width self.height = height def area(self): return self.width * self.height def perimeter(self): return 2 * (self.width + self.height) # 多态演示 shapes = [Circle(5), Rectangle(4, 6)] for shape in shapes: print(f"面积: {shape.area():.2f}, 周长: {shape.perimeter():.2f}") # 输出: # 面积: 78.54, 周长: 31.42 # 面积: 24.00, 周长: 20.00 ``` --- #### **练习3:日志记录装饰器装饰器应用)** **需求**: 1. 创建装饰器`log_execution`,记录方法的执行间和参数 2. 将装饰器应用于银行账户的`deposit`和`withdraw`方法 3. 使用闭包捕获函数执行状态 ```python import time def log_execution(func): def wrapper(*args, **kwargs): start = time.time() result = func(*args, **kwargs) end = time.time() print(f"[LOG] 执行 {func.__name__},耗: {end-start:.4f}秒,参数: {args[1:]}") return result return wrapper class Account: # ... (同练习1的Account) @log_execution def deposit(self, amount): # ... (同练习1) @log_execution def withdraw(self, amount): # ... (同练习1) # 测试 acc = Account("ACC001", 1000) acc.deposit(500) # 输出: [LOG] 执行 deposit,耗: 0.0001秒,参数: (500,) ``` --- #### **练习4:访问控制强化(私有属性与异常处理)** **需求**: 1. 在`Account`中添加私有属性`_transaction_history`(交易历史) 2. 通过方法`add_transaction()`添加记录(禁止直接访问) 3. 使用`@property`提供只读访问接口 ```python class Account: def __init__(self, account_id): self.account_id = account_id self._balance = 0 self._transaction_history = [] # 私有属性 def add_transaction(self, action, amount): if amount <= 0: raise ValueError("金额必须为正数") self._transaction_history.append((action, amount)) @property def transaction_history(self): return self._transaction_history.copy() # 返回副本防止外部修改 # 测试 acc = Account("ACC002") acc.add_transaction("存款", 500) print(acc.transaction_history) # 输出: [('存款', 500)] acc.transaction_history.clear() # 失败(返回的是副本) ``` --- #### **练习5:装饰器实现单例模式** **需求**: 1. 创建装饰器`singleton`,确保被装饰的只有一个实例 2. 测试`DatabaseConnection`在不同位置调用返回相同实例 ```python def singleton(cls): instances = {} def get_instance(*args, **kwargs): if cls not in instances: instances[cls] = cls(*args, **kwargs) return instances[cls] return get_instance @singleton class DatabaseConnection: def __init__(self, db_url): self.db_url = db_url # 测试 conn1 = DatabaseConnection("mysql://localhost") conn2 = DatabaseConnection("postgres://remote") print(conn1 is conn2) # 输出: True(相同实例) print(conn1.db_url) # 输出: mysql://localhost ``` --- ### 关键知识点总结 1. **封装**:通过私有属性(`_balance`)和访问控制器(`@property`)保护数据完整性[^1] 2. **多态**:子重写父抽象方法(`Shape`的`area()`),实现统一接口不同行为[^1] 3. **装饰器**:基于闭包实现横切关注点(如日志、性能监控)与业务逻辑分离[^2][^3] 4. **访问控制**:利用私有属性和异常处理强制数据操作规则 5. **设计模式**:装饰器实现单例模式,控制对象创建过程
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值