Python面向对象中的封装详情

当我们使用Python面向对象编程时,封装就是隐藏了类的内部细节,不让外部代码随意修改类的属性和方法,让对象的使用更加安全和方便。接下来,我将详细讲解Python面向对象中的封装。

封装的基本原则

在Python面向对象中,封装主要体现在以下几个方面:

  • 属性和方法的访问权限控制
  • 使用属性访问器来访问对象的属性
  • 将对象的复杂实现细节隐藏起来

封装的基本原则是:对外提供公共接口,而不关心接口的内部实现。这样可以确保类的修改不会影响外部代码的使用。在Python中,通过使用___前缀来控制类成员的访问权限,下面我们来详细讲解一下这些内容。

属性和方法的访问权限控制

在Python中,我们可以使用publicprotectedprivate属性来控制成员的访问权限。其中,public属性的成员可以被任何外部代码访问;protected属性的成员只能被子类和同一模块中的代码访问;private属性的成员只能在类的内部被访问。

Python中使用下划线(_)来实现属性的控制。

  • 使用一个下划线前缀的成员,表示这个成员属性和方法是保护的(protected),外部不应该访问到。
  • 使用两个下划线前缀的成员,表示该成员是私有的(private),只有类内部可以访问,外部代码无法直接访问。

示例1:使用下划线前缀实现属性的保护(protected)

class Person:
    def __init__(self, name, age):
        self._name = name  # 带下划线的名字表示受保护的属性
        self._age = age    # 带下划线的名字表示受保护的属性

    def _show_info(self):  # 带下划线的名字表示受保护的方法
        print(f"姓名:{self._name},年龄:{self._age}")

class Student(Person):
    def __init__(self, name, age, grade):
        super().__init__(name, age)
        self.grade = grade

    def show_info(self):
        self._show_info()         # 通过受保护的方法访问父类的属性
        print(f"年级:{self.grade}")

s = Student("小明", 18, "初一")
s.show_info()

输出结果为:

姓名:小明,年龄:18
年级:初一

示例2:使用双下划线前缀实现属性的封装(private)

class Person:
    def __init__(self, name, age):
        self.__name = name  # 使用双下划线实现属性的私有化
        self.__age = age    # 使用双下划线实现属性的私有化

    def __show_info(self):  # 使用双下划线实现方法的私有化
        print(f"姓名:{self.__name},年龄:{self.__age}")

class Student(Person):
    def __init__(self, name, age, grade):
        super().__init__(name, age)
        self.grade = grade

    def show_info(self):
        self.__show_info()      # 不能直接访问父类的私有方法

s = Student("小明", 18, "初一")
s.show_info()

这时运行代码会发现报错:

AttributeError: 'Student' object has no attribute '__show_info'

原因是在Python中,使用双下划线前缀(__)声明的成员,会自动转换为_类名__成员名的格式,从而实现了私有成员的访问限制。修改show_info()方法为_Person__show_info()即可实现。

使用属性访问器

Python中属性的封装不止限于访问权限控制,还可以使用属性访问器来实现。

属性访问器可分为getter和setter两种,getter用于获取属性的值,而setter用于设置属性的值。属性访问器将属性的访问方式封装成一个函数,使其更方便灵活的使用。

示例3:使用属性访问器实现身份证号的封装

class Student:
    def __init__(self, name, age, id_card):
        self.name = name
        self.age = age
        self.__id_card = id_card     # 使用双下划线实现身份证号的私有化

    @property
    def id_card(self):               # getter方法
        return self.__id_card

    @id_card.setter
    def id_card(self, value):        # setter方法
        if len(value) != 18:
            raise ValueError("身份证号必须为18位")
        self.__id_card = value

s = Student("小明", 18, "123456789012345678")
print(s.id_card)             # 通过getter获取身份证号
s.id_card = "123456789012345678"  # 通过setter设置身份证号
print(s.id_card)

输出结果为:

123456789012345678
123456789012345678

隐藏对象的复杂实现细节

在面向对象设计中,一个好的类不仅需要具备良好的封装性,同时还需要隐藏具体的实现细节,使类的使用者只需要关心类提供的功能就可以了,而无需关心其具体的内部实现。实现的方法可以使用大量的细节实现,但充分利用私有属性和方法能够提供类的一个好的外部接口为使用者隐藏细节的方式。

示例4:使用双下划线前缀实现购物车数量的封装

class ShoppingCart:
    def __init__(self):
        self.__items = []             # 使用双下划线实现购物车数量的私有化

    def add_item(self, item):
        self.__items.append(item)

    def remove_item(self, item):
        self.__items.remove(item)

    def get_item_count(self):
        return len(self.__items)

s = ShoppingCart()
for i in range(5):
    s.add_item("item" + str(i))

print(s.get_item_count())   # 只能通过类的方法访问私有属性
s.__items = []              # 无法直接修改私有属性
print(s.get_item_count())

输出结果为:

5
5

在此示例中,ShoppingCart类使用双下划线私有化__items属性,只能通过类的方法进行访问,同时使用了add_itemremove_item方法来操作购物车内的商品。这样,类的使用者只需要关注商品数目的添加、移除和获取,而无需关心其内部的具体实现细节。

总结

Python中面向对象编程中的封装是保护类的内部实现,不让外部代码随意修改类的属性和方法,让对象的使用更加安全和方便。在Python中,使用下划线和双下划线前缀来控制成员的访问权限,同时使用属性访问器来获取和设置属性的值。此外,还可以使用私有属性和方法来隐藏类的内部实现细节。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Python面向对象中的封装详情 - Python技术站

(0)
上一篇 2023年6月25日
下一篇 2023年6月25日

相关文章

  • PHP和Mysqlweb应用开发核心技术 第1部分 Php基础-3 代码组织和重用2

    “PHP和MysqlWeb应用开发核心技术”一书是一本非常实用的PHP和MySQL开发参考资料,其中第一部分Php基础第三章讲解了代码组织和重用的相关知识,下面将为大家详细讲解具体攻略。 代码组织和重用 文件包含 在PHP中,可以通过include和require语句将一个PHP文件引入到另一个PHP文件中。使用include或require语句可以将一个P…

    other 2023年6月26日
    00
  • iphone设备总是提示存储空间不足怎么办 iphone存储空间清理方法教程

    iPhone设备提示存储空间不足怎么办? 背景 随着 iPhone 发展,手机内置存储空间不断增加,但是由于用户需求的不断增长,存储空间问题仍然是很普遍的。很多用户在使用 iPhone 常常会遇到 iPhone 设备内存不足的情况,这对用户的正常使用造成了很大的困扰。下面给出 iPhone 存储空间的清理方法。 iPhone存储空间清理方法教程 1. 清理照…

    other 2023年6月28日
    00
  • 在scrollView中使用pageControl

    在 UIScrollView 中使用 UIPageControl UIScrollView 是 iOS 开发中经常使用的界面元素,可以用于展示滑动列表、缩小放大操作等。而 UIPageControl 是一个用于显示页面的指示器,一般用于指示 UIScrollView 中当前所在的页面。本文将介绍如何在 UIScrollView 中使用 UIPageContr…

    其他 2023年3月28日
    00
  • 当前磁盘格式为fat32无法复制超大文件怎么办?

    当我们在使用fat32格式的磁盘时,会发现无法复制超大文件,因为fat32格式的磁盘只支持最大4GB的单文件大小。如果我们要复制超过4GB的文件时,需要采取以下两种方法来解决此问题。 方法一:将磁盘格式化为NTFS格式 将磁盘格式化为NTFS格式是解决这个问题的最常见方法。步骤如下: 打开“我的电脑”,找到需要格式化的磁盘,右键单击磁盘,选择“格式化”选项。…

    other 2023年6月27日
    00
  • 使用springmvc临时不使用视图解析器的自动添加前后缀

    使用Spring MVC时,可以通过配置视图解析器来自动添加前后缀,以便简化控制器方法返回视图的操作。但有时候我们需要临时禁用视图解析器,即不添加前后缀,这在某些特殊情况下非常有用。下面是使用Spring MVC临时不使用视图解析器的完整攻略: 创建Spring MVC项目并配置视图解析器: 在Spring MVC项目的配置文件(如applicationCo…

    other 2023年8月6日
    00
  • Docker创建镜像、怎么修改、上传镜像等详细介绍

    下文将详细介绍Docker创建镜像、修改和上传镜像的过程。包括使用示例说明。 创建镜像 首先需要编写Dockerfile,Dockerfile是一种文本文件,包含了构建Docker镜像的指令。 打开终端或者命令行,并进入到Dockerfile所在的目录。 执行以下命令创建Docker镜像: $ docker build –tag <your_imag…

    other 2023年6月27日
    00
  • C++移动语义详细介绍使用

    C++移动语义详细介绍使用 什么是移动语义 C++11引入移动语义的主要目的是为了提高代码的效率。传统的C++使用拷贝构造函数深拷贝的方式实现对象传递,对于大量数据的传递效率非常低下。而移动语义则是通过移动资源的方式来实现对象传递,不需要进行不必要的复制操作,从而提高效率。 C++11中规定,如果一个对象的资源可以被移动,那么这个对象就是可移动的。 如何使用…

    other 2023年6月26日
    00
  • linux 进行批量下载文件操作

    linux 进行批量下载文件操作 在日常的工作中,我们可能会需要下载许多文件,如果一个个手动下载会比较耗时费力。不过在 Linux 系统中,我们可以使用一些命令来进行批量下载,提高我们的效率。 使用 wget 下载文件 wget 是一个常用的下载工具,它可以从 HTTP、HTTPS、FTP 等协议中下载文件。使用 wget 下载文件非常简单,只需要在终端中输…

    其他 2023年3月29日
    00
合作推广
合作推广
分享本页
返回顶部