在Python中进行封装

在Python中,封装是一种面向对象编程(OOP)的特性,它允许我们将数据(属性)和操作这些数据的方法(函数)捆绑在一起,形成一个独立的对象。封装的主要目的是隐藏对象的内部状态,并只通过对象提供的方法来访问和操作这些状态,用于保护对象的数据完整性,并防止外部代码直接访问或修改对象的内部状态。

Python中的封装可以通过定义类来实现,在类中,我们可以将属性和方法定义为私有(只能在类内部访问)或公有(可以在类外部访问)。

以下是一个案例,在自创建的Person类,使用双下划线前缀进行标识两个私有属性__name__age,以及四个公有方法get_name()get_age()set_name()set_age(),采用公共方法获取其私有属性,同时对修改私有属性进行了合法性检查,在公共方法修改了属性值后如果某个属性值错误,会进行报错并取消该属性的修改

进行封装了的类:

python 复制代码
class Person:  
    def __init__(self, name, age, height, width):  
        # 私有属性,使用双下划线前缀  
        self.__name = name  
        self.__age = age
        self.__height = height
        self.__width = width
  
    # 公有方法,用于获取私有属性的值  
    def get_name(self):  
        return self.__name  
  
    def get_age(self):  
        return self.__age

    def get_height(self):  
        return self.__height

    def get_width(self):  
        return self.__width  
  
    # 公有方法,用于设置私有属性的值  
    def set_name(self, name):  
        self.__name = name  
  
    def set_age(self, age):  
        if age >= 0 and age <= 120:  # 对年龄进行合法性检查  
            self.__age = age  
        else:  
            print("Invalid age!")

    def set_height(self, height):  
        if height >= 0 and height <= 250:  # 对身高进行合法性检查  
            self.__height = height  
        else:  
            print("Invalid height!") 

    def set_width(self, width):  
        if width >= 50 and width <= 500:  # 对体重进行合法性检查  
            self.__width = width  
        else:  
            print("Invalid width!")
  
# 创建Person对象  
person = Person("Alice", 25, 140, 100)  
  
# 通过公有方法访问和修改私有属性  
print(f"name:{person.get_name()}, age:{person.get_age()}, height:{person.get_height()},width:{person.get_width()}")  
person.set_name("Bob")  
person.set_age(-5)
person.set_height(300)
person.set_width(550)  
print(f"name:{person.get_name()}, age:{person.get_age()}, height:{person.get_height()},width:{person.get_width()}")  
 

这里可以看到age(-5)、width(550)、height(300)这三个错误的属性值进行了报错并取消了修改

python 复制代码
name:Alice, age:25, height:140,width:100
Invalid age!
Invalid height!
Invalid width!
name:Bob, age:25, height:140,width:100

未进行封装的类:

直接使用公共类并访问和修改属性

python 复制代码
class Person:    
    def __init__(self, name, age, height, width):    
        self.name = name    
        self.age = age  
        self.height = height  
        self.width = width  
  
# 创建Person对象    
person = Person("Alice", 25, 140, 100)    
    
# 直接访问和修改属性    
print(f"name:{person.name}, age:{person.age}, height:{person.height}, width:{person.width}")    
person.name = "Bob"    
person.age = 30  
person.height = 160  
person.width = 200  
print(f"name:{person.name}, age:{person.age}, height:{person.height}, width:{person.width}")

# 创建一个新的Person对象并尝试设置无效的属性值  
invalid_person = Person("Charlie", -5, 300, 600) 
  
# 输出这个对象属性
print(f"name:{invalid_person.name}, age:{invalid_person.age}, height:{invalid_person.height}, width:{invalid_person.width}")

这里可以看到终端输出的信息中,Charlie的年龄和身高体重存在明显问题,是无效属性值,而且也展示了未进行封装的坏处:

  1. 数据完整性受损:没有对数据进行合法性检查,无效或不合理的数据可以被接受并存储在对象中。

  2. 代码可维护性降低:如果后续需要添加额外的逻辑来处理属性,需要找到并修改所有直接修改属性的代码,而不是只修改一个setter方法。

  3. 安全性问题:对象的内部状态可以被外部代码随意修改,可能导致对象处于不一致或不稳定的状态。

  4. 封装性丧失:封装是面向对象编程的四大基本原则之一,它允许我们隐藏对象的内部实现细节,只通过明确定义的接口与外界交互。未封装的类违反了这一原则。

python 复制代码
name:Alice, age:25, height:140, width:100
name:Bob, age:30, height:160, width:200
name:Charlie, age:-5, height:300, width:600

这里新建一个用于绘制年龄、身高、体重条形图的Python文件,继承上述代码中的Person类,并创建实例进行图形绘制

python 复制代码
import matplotlib.pyplot as plt  
from Encapsulation import Person   
  
class StatisticsPerson(Person):  
    instances = []  # 类变量,用于存储实例  
  
    def __init__(self, name, age, height, width):  
        super().__init__(name, age, height, width)  
        self.instances.append(self)  # 将新创建的实例添加到instances列表中  
  
    # 使用静态方法统计所有人的年龄、身高和宽度,并绘制条状图  
    @staticmethod  
    def plot_statistics():  
        ages = [person.get_age() for person in StatisticsPerson.instances]  
        heights = [person.get_height() for person in StatisticsPerson.instances]  
        widths = [person.get_width() for person in StatisticsPerson.instances]  
  
        x = range(len(StatisticsPerson.instances))  
  
        plt.figure(figsize=(10, 6))  
        plt.bar(x, ages, label='Age', width=0.25)  
        plt.bar([i + 0.25 for i in x], heights, label='Height', width=0.25)  
        plt.bar([i + 0.5 for i in x], widths, label='Width', width=0.25)  
  
        plt.xlabel('Name')  
        plt.ylabel('Values')  
        plt.title('Comparison of Age, Height, and Width')  
        plt.xticks([i + 0.25 for i in x], [person.get_name() for person in StatisticsPerson.instances], rotation=45)  
        plt.legend() 
        plt.savefig("GGboy.png") 
        plt.show()  
  
# 创建StatisticsPerson对象  
person1 = StatisticsPerson("Alice", 25, 140, 100)  
person2 = StatisticsPerson("Bob", 30, 160, 200)  
person3 = StatisticsPerson("Charlie", 40, 175, 150)  
  
# 绘制并保存统计图  
StatisticsPerson.plot_statistics()

生成的图片:

相关推荐
databook21 小时前
Manim实现闪光轨迹特效
后端·python·动效
Juchecar1 天前
解惑:NumPy 中 ndarray.ndim 到底是什么?
python
用户8356290780511 天前
Python 删除 Excel 工作表中的空白行列
后端·python
Json_1 天前
使用python-fastApi框架开发一个学校宿舍管理系统-前后端分离项目
后端·python·fastapi
数据智能老司机1 天前
精通 Python 设计模式——分布式系统模式
python·设计模式·架构
数据智能老司机1 天前
精通 Python 设计模式——并发与异步模式
python·设计模式·编程语言
数据智能老司机1 天前
精通 Python 设计模式——测试模式
python·设计模式·架构
数据智能老司机1 天前
精通 Python 设计模式——性能模式
python·设计模式·架构
c8i1 天前
drf初步梳理
python·django
每日AI新事件1 天前
python的异步函数
python